diff options
842 files changed, 25225 insertions, 12585 deletions
@@ -1,5 +1,6 @@ syntax: glob + # WinMerge temp files *.bak # Compiled python bytecode @@ -67,3 +68,4 @@ glob:indra/newview/filters.xml glob:indra/newview/avatar_icons_cache.txt glob:indra/newview/avatar_lad.log glob:*.diff +*.rej @@ -110,6 +110,7 @@ bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 DRTVWR-52_2.6.6-beta1 bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 2.6.6-beta1 5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start beafa8a9bd1d1b670b7523d865204dc4a4b38eef DRTVWR-55_2.6.8-beta1 +bb9932a7a5fd00edf52d95f354e3b37ae6a942db DRTVWR-156 beafa8a9bd1d1b670b7523d865204dc4a4b38eef 2.6.8-beta1 11d5d8080e67c3955914caf98f2eb116af30e55a 2.6.9-start e67da2c6e3125966dd49eef98b36317afac1fcfe 2.6.9-start @@ -149,6 +150,7 @@ a9abb9633a266c8d2fe62411cfd1c86d32da72bf 2.7.1-release 09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1 e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start 502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start +2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155 6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release 6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1 @@ -259,5 +261,55 @@ c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release 3d75c836d178c7c7e788f256afe195f6cab764a2 DRTVWR-111_3.2.7-beta1 3d75c836d178c7c7e788f256afe195f6cab764a2 3.2.7-beta1 89980333c99dbaf1787fe20784f1d8849e9b5d4f 3.2.8-start +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 +51b2fd52e36aab8f670e0874e7e1472434ec4b4a 3.2.8-release +e9c82fca5ae6fb8a8af29012d78fb194a29323f3 DRTVWR-117_3.2.9-beta1 +e9c82fca5ae6fb8a8af29012d78fb194a29323f3 3.2.9-beta1 +a01ef9bed28627f4ca543fbc1d70c79cc297a90f DRTVWR-118_3.2.9-beta2 +a01ef9bed28627f4ca543fbc1d70c79cc297a90f 3.2.9-beta2 +987425b1acf4752379b2e1eb20944b4b35d67a85 3.2.8-beta2 +d5f263687f43f278107363365938f0a214920a4b DRTVWR-119 +d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1 +5e8d2662f38a66eca6c591295f5880d47afc73f7 viewer-release-candidate +5e8d2662f38a66eca6c591295f5880d47afc73f7 3.3.0-release +d5f263687f43f278107363365938f0a214920a4b 3.3.0-start +dffd0457ee0745de65bf95f0642a5c9e46b8e2f0 viewer-beta-candidate +d5f263687f43f278107363365938f0a214920a4b DRTVWR-119 +d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1 +5e8d2662f38a66eca6c591295f5880d47afc73f7 viewer-release-candidate +5e8d2662f38a66eca6c591295f5880d47afc73f7 3.3.0-release +28b95a6a28dca3338d9a1f4f204b96678df9f6a5 viewer-beta-candidate +b43cd25be49e3984ff5361cefad020e069131d98 3.3.1-start +3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 DRTVWR-125 +3e2fca4ed1a0dc9fe6d8a6664e71098bb035a367 3.3.1-start +28b95a6a28dca3338d9a1f4f204b96678df9f6a5 3.3.1-beta1 +1dc545e44617975da2a4a32fe303386c687a6ca1 viewer-beta-candidate +1dc545e44617975da2a4a32fe303386c687a6ca1 3.3.1-beta2 +1dc545e44617975da2a4a32fe303386c687a6ca1 DRTVWR-139 +5e8d2662f38a66eca6c591295f5880d47afc73f7 viewer-release-candidate +c623bbc854b6f7ee1b33a3718f76715046aa2937 viewer-release-candidate +c623bbc854b6f7ee1b33a3718f76715046aa2937 3.3.1-release +d29a260119f8d5a5d168e25fed0c7ea6b3f40161 3.3.2-beta1 +675668bd24d3bea570814f71762a2a806f7e1b8d 3.3.2-beta2 +c623bbc854b6f7ee1b33a3718f76715046aa2937 viewer-release-candidate +675668bd24d3bea570814f71762a2a806f7e1b8d viewer-release-candidate +675668bd24d3bea570814f71762a2a806f7e1b8d 3.3.2-release +675668bd24d3bea570814f71762a2a806f7e1b8d viewer-release-candidate +9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157 +a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159 +24a7281bef42bd4430ceb25db8b195449c2c7de3 DRTVWR-153 +15e90b52dc0297921b022b90d10d797436b8a1bd viewer-release-candidate +6414ecdabc5d89515b08d1f872cf923ed3a5523a DRTVWR-148 +1b7f311b5a5dbfbed3dcbb4ed44afa20f89cad4c DRTVWR-144 +1b7f311b5a5dbfbed3dcbb4ed44afa20f89cad4c 3.3.3-beta1 +5910f8063a7e1ddddf504c2f35ca831cc5e8f469 DRTVWR-160 +1b7f311b5a5dbfbed3dcbb4ed44afa20f89cad4c 3.3.3-beta1 +f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 3.3.3-beta1 +1b7f311b5a5dbfbed3dcbb4ed44afa20f89cad4c DRTVWR-144 +f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 DRTVWR-144 diff --git a/BuildParams b/BuildParams index c051397853..6f1af583f0 100644 --- a/BuildParams +++ b/BuildParams @@ -35,51 +35,27 @@ viewer-development.build_debug_release_separately = true # Notifications - to configure email notices, add a setting like this: # <username>_<reponame>.email = <email-address> + # ================================================================= -# Viewer Development (snowstorm canonical build owned by Oz Linden) +# Canonical viewer integration builds - Oz Linden # ================================================================= -snowstorm_viewer-development.viewer_channel = "Second Life Development" -snowstorm_viewer-development.login_channel = "Second Life Development" -snowstorm_viewer-development.build_viewer_update_version_manager = false -snowstorm_viewer-development.email = viewer-development-builds@lists.secondlife.com -snowstorm_viewer-development.build_enforce_coding_policy = true -snowstorm_viewer-development.codeticket_add_context = true - -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 +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 (Owner: Dessie Linden) -# ======================================== 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-pre-beta.viewer_channel = "Second Life Beta Viewer" -viewer-pre-beta.login_channel = "Second Life Beta Viewer" -viewer-pre-beta.build_debug_release_separately = true -viewer-pre-beta.build_viewer_update_version_manager = true - - -# ======================================== -# Viewer Release (Owner: Dessie Linden) -# ======================================== 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 -viewer-pre-release.viewer_channel = "Second Life Release" -viewer-pre-release.login_channel = "Second Life Release" -viewer-pre-release.build_debug_release_separately = true -viewer-pre-release.build_viewer_update_version_manager = true -#viewer-pre-release.release-viewer.jira = DRTVWR-92 - - # ======================================== # mesh-development # ======================================== @@ -140,6 +116,12 @@ viewer-mesh.email = shining@lists.lindenlab.com # 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 @@ -156,19 +138,6 @@ 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-1.build_debug_release_separately = true -oz_project-1.codeticket_add_context = false -oz_project-1.email = oz@lindenlab.com -oz_project-2.build_debug_release_separately = true -oz_project-2.codeticket_add_context = false -oz_project-2.email = oz@lindenlab.com -oz_project-3.build_debug_release_separately = true -oz_project-3.codeticket_add_context = false -oz_project-3.email = oz@lindenlab.com -oz_project-4.build_debug_release_separately = true -oz_project-4.codeticket_add_context = false -oz_project-4.email = oz@lindenlab.com - # ================================================================= # asset delivery 2010 projects # ================================================================= @@ -199,4 +168,35 @@ simon_viewer-dev-private.email_status_this_is_os = false vir-project-1.viewer_channel = "Second Life Release" vir-project-1.login_channel = "Second Life Release" +# ======================================== +# THX-1138 / Runway projects +# ======================================== +viewer-thx1138-runway-shared.viewer_channel = "Project Viewer - THX-1138 Runway" +viewer-thx1138-runway-shared.login_channel = "Project Viewer - THX-1138 Runway" +viewer-thx1138-runway-shared.viewer_grid = uma +viewer-thx1138-runway-shared.build_debug_release_separately = true +viewer-thx1138-runway-shared.build_CYGWIN_Debug = false +viewer-thx1138-runway-shared.build_viewer_update_version_manager = false + +viewer-thx1138.viewer_channel = "Project Viewer - THX-1138" +viewer-thx1138.login_channel = "Project Viewer - THX-1138" +viewer-thx1138.viewer_grid = uma +viewer-thx1138.build_debug_release_separately = true +viewer-thx1138.build_CYGWIN_Debug = false +viewer-thx1138.build_viewer_update_version_manager = false + +runway-merge.viewer_channel = "Project Viewer - Runway Merge" +runway-merge.login_channel = "Project Viewer - Runway Merge" +runway-merge.viewer_grid = agni +runway-merge.build_debug_release_separately = true +runway-merge.build_CYGWIN_Debug = false +runway-merge.build_viewer_update_version_manager = false + +runway.viewer_channel = "Project Viewer - Runway" +runway.login_channel = "Project Viewer - Runway" +runway.viewer_grid = agni +runway.build_debug_release_separately = true +runway.build_CYGWIN_Debug = false +runway.build_viewer_update_version_manager = false + # eof diff --git a/autobuild.xml b/autobuild.xml index 9914be6867..d58c4a350c 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -90,9 +90,9 @@ <key>archive</key> <map> <key>hash</key> - <string>9868bfa0b6954e4884c49c6f30068c80</string> + <string>1fe7c2121916b2c5ff75073742442e2a</string> <key>url</key> - <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-darwin-20110217.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/257886/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120523.tar.bz2</string> </map> <key>name</key> <string>darwin</string> @@ -102,9 +102,9 @@ <key>archive</key> <map> <key>hash</key> - <string>ff62946c518a247c86e1066c1e9a5855</string> + <string>eac7926a7caa121144c911434a01b680</string> <key>url</key> - <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-linux-20110309.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/257886/arch/Linux/installer/apr_suite-1.4.5-linux-20120523.tar.bz2</string> </map> <key>name</key> <string>linux</string> @@ -114,9 +114,9 @@ <key>archive</key> <map> <key>hash</key> - <string>73785c200a5b4ef74a1230b028bb680d</string> + <string>8789d952a33ce3e8b87be8cbf94bc6ba</string> <key>url</key> - <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-windows-20110217.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/257886/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120523.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -1206,9 +1206,9 @@ <key>archive</key> <map> <key>hash</key> - <string>26aa7c367ffadd573f61a6a96f820f80</string> + <string>4a98d727561cd1f4ac5ee02907411df1</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/245988/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20111201.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/250147/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20120228.tar.bz2</string> </map> <key>name</key> <string>darwin</string> @@ -1218,9 +1218,9 @@ <key>archive</key> <map> <key>hash</key> - <string>c05a33ee8b6f253b5a744596dfc3707d</string> + <string>f50e5f0cc880c55b3f0f7e67dc8f7221</string> <key>url</key> - <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-qt4.6-20101013.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/250147/arch/Linux/installer/llqtwebkit-4.7.1-linux-20120228.tar.bz2</string> </map> <key>name</key> <string>linux</string> @@ -1230,9 +1230,9 @@ <key>archive</key> <map> <key>hash</key> - <string>270db8568a0c4bab266d98e1a820aec4</string> + <string>5e3cd6af397e853a963a6de40d440ff4</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/245988/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20111201.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/250147/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20120228.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -132,10 +132,6 @@ if test -f scripts/update_version_files.py ; then end_section UpdateVer fi -# Now retrieve the version for use in the version manager -# First three parts only, $revision will be appended automatically. -build_viewer_update_version_manager_version=`python scripts/get_version.py --viewer-version | sed 's/\.[0-9]*$//'` - if [ -z "$AUTOBUILD" ] then export autobuild_dir="$here/../../../autobuild/bin/" @@ -177,9 +173,6 @@ eval "$("$AUTOBUILD" source_environment)" env|sort -# Install packages. -"$AUTOBUILD" install --skip-license-check - # Now run the build succeeded=true build_processes= @@ -195,10 +188,19 @@ do begin_section "Do$variant" build_dir=`build_dir_$arch $variant` build_dir_stubs="$build_dir/win_setup/$variant" + + begin_section "PreClean" rm -rf "$build_dir" + end_section "PreClean" + mkdir -p "$build_dir" mkdir -p "$build_dir/tmp" - #export TMP="$build_dir/tmp" + + # Install packages. + begin_section "AutobuildInstall" + "$AUTOBUILD" install --verbose --skip-license-check + end_section "AutobuildInstall" + if pre_build "$variant" "$build_dir" >> "$build_log" 2>&1 then if $build_link_parallel diff --git a/doc/contributions.txt b/doc/contributions.txt index 0b740dc456..ee2a760567 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -103,6 +103,7 @@ Aleric Inglewood STORM-163 STORM-955 STORM-960 + STORM-1793 Ales Beaumont VWR-9352 SNOW-240 @@ -233,7 +234,7 @@ Borg Capalini Boroondas Gupte OPEN-29 OPEN-39 - OPEN-39 + OPEN-54 OPEN-99 SNOW-278 SNOW-503 @@ -395,6 +396,8 @@ Frontera Thor Fury Rosewood Gaberoonie Zanzibar Ganymedes Costagravas +Geenz Spad + STORM-1823 Gene Frostbite GeneJ Composer Geneko Nemeth @@ -466,6 +469,9 @@ Hiro Sommambulist VWR-132 VWR-136 VWR-143 +Hitomi Tiponi + STORM-1741 + STORM-1862 Holger Gilruth Horatio Freund Hoze Menges @@ -594,23 +600,44 @@ Jonathan Yap STORM-1659 STORM-1674 STORM-1685 + STORM-1718 STORM-1721 + STORM-1718 STORM-1727 STORM-1725 STORM-1719 STORM-1712 STORM-1728 STORM-1736 + STORM-1804 STORM-1734 STORM-1731 STORM-653 STORM-1737 STORM-1733 + STORM-1741 STORM-1790 + STORM-1795 STORM-1788 + STORM-1803 + STORM-1795 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-1858 + STORM-1862 Kadah Coba STORM-1060 Jondan Lundquist @@ -646,6 +673,7 @@ Kitty Barnett STORM-1001 STORM-1175 VWR-24217 + STORM-1804 Kolor Fall Komiko Okamoto Korvel Noh @@ -853,6 +881,7 @@ Nicky Perian OPEN-1 STORM-1087 STORM-1090 + STORM-1828 Nicoladie Gymnast Nounouch Hapmouche VWR-238 @@ -1140,9 +1169,9 @@ Tofu Buzzard CTS-411 STORM-546 VWR-24509 - STORM-1684 SH-2477 STORM-1684 + STORM-1819 Tony Kembia Torben Trautman TouchaHoney Perhaps @@ -1172,6 +1201,8 @@ Unlikely Quintessa UsikuFarasi Kanarik Vadim Bigbear VWR-2681 +Vaalith Jinn + STORM-64 Vector Hastings VWR-8726 Veritas Raymaker @@ -1240,6 +1271,8 @@ WolfPup Lowenhar VWR-20741 VWR-20933 Wundur Primbee +Xellessanova Zenith + STORM-1793 Xiki Luik xstorm Radek YongYong Francois @@ -1263,6 +1296,7 @@ Zi Ree VWR-24017 VWR-25588 STORM-1790 + STORM-1842 Zipherius Turas VWR-76 VWR-77 diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 4b1bf49d07..1cebb53a07 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -66,7 +66,6 @@ if (VIEWER) add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger) add_subdirectory(${LIBS_OPEN_PREFIX}llplugin) add_subdirectory(${LIBS_OPEN_PREFIX}llui) - add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml) add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components) # Legacy C++ tests. Build always, run if LL_TESTS is true. diff --git a/indra/cmake/JsonCpp.cmake b/indra/cmake/JsonCpp.cmake index 499b00fb44..7ad73e5683 100644 --- a/indra/cmake/JsonCpp.cmake +++ b/indra/cmake/JsonCpp.cmake @@ -18,5 +18,5 @@ else (STANDALONE) elseif (LINUX) set(JSONCPP_LIBRARIES libjson_linux-gcc-4.1.3_libmt.a) endif (WINDOWS) - set(JSONCPP_INCLUDE_DIRS "${LIBS_PREBUILT_DIR}/include/jsoncpp" "${LIBS_PREBUILT_DIR}/include/json") + set(JSONCPP_INCLUDE_DIR "${LIBS_PREBUILT_DIR}/include/jsoncpp" "${LIBS_PREBUILT_DIR}/include/json") endif (STANDALONE) diff --git a/indra/cmake/LLTestCommand.cmake b/indra/cmake/LLTestCommand.cmake index b5a0580a90..f75c23a5de 100644 --- a/indra/cmake/LLTestCommand.cmake +++ b/indra/cmake/LLTestCommand.cmake @@ -9,6 +9,9 @@ MACRO(LL_TEST_COMMAND OUTVAR LD_LIBRARY_PATH) FOREACH(dir ${LD_LIBRARY_PATH}) LIST(APPEND value "-l${dir}") ENDFOREACH(dir) + # Enough different tests want to be able to find CMake's PYTHON_EXECUTABLE + # that we should just pop it into the environment for everybody. + LIST(APPEND value "-DPYTHON=${PYTHON_EXECUTABLE}") LIST(APPEND value ${ARGN}) SET(${OUTVAR} ${value}) ##IF(LL_TEST_VERBOSE) diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index c5f9e2c579..47f944f9a5 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -13,7 +13,7 @@ elseif (LINUX) set(EXE_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs/bin) elseif (DARWIN) set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs) - set(EXE_STAGING_DIR "${CMAKE_BINARY_DIR}/sharedlibs/\$(CONFIGURATION)") + set(EXE_STAGING_DIR "${CMAKE_BINARY_DIR}/sharedlibs") endif (WINDOWS) # Autobuild packages must provide 'release' versions of libraries, but may provide versions for @@ -33,7 +33,14 @@ else(WINDOWS OR DARWIN) set(AUTOBUILD_LIBS_INSTALL_DIRS ${AUTOBUILD_INSTALL_DIR}/lib/${CMAKE_BUILD_TYPE_LOWER}) endif(WINDOWS OR DARWIN) -list(APPEND AUTOBUILD_LIBS_INSTALL_DIRS ${ARCH_PREBUILT_DIRS_RELEASE}) +if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release") + # When we're building something other than Release, append the + # packages/lib/release directory to deal with autobuild packages that don't + # provide (e.g.) lib/debug libraries. + list(APPEND AUTOBUILD_LIBS_INSTALL_DIRS ${ARCH_PREBUILT_DIRS_RELEASE}) + message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}, extending AUTOBUILD_LIBS_INSTALL_DIRS") +endif (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release") +message(STATUS "For ${CMAKE_BUILD_TYPE}, AUTOBUILD_LIBS_INSTALL_DIRS: ${AUTOBUILD_LIBS_INSTALL_DIRS}") link_directories(${AUTOBUILD_LIBS_INSTALL_DIRS}) if (LINUX) diff --git a/indra/cmake/VisualLeakDetector.cmake b/indra/cmake/VisualLeakDetector.cmake new file mode 100644 index 0000000000..d3ba554e46 --- /dev/null +++ b/indra/cmake/VisualLeakDetector.cmake @@ -0,0 +1,15 @@ +# -*- cmake -*- + +if (VIEWER) + + set(INCLUDE_VLD_CMAKE OFF CACHE BOOL "Build the Windows viewer with Visual Leak Detector turned on or off") + + if (INCLUDE_VLD_CMAKE) + + if (WINDOWS) + add_definitions(-DINCLUDE_VLD=1) + endif (WINDOWS) + + endif (INCLUDE_VLD_CMAKE) + +endif (VIEWER) diff --git a/indra/cmake/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake index 91b49e75d7..d9df78bfc8 100644 --- a/indra/cmake/WebKitLibPlugin.cmake +++ b/indra/cmake/WebKitLibPlugin.cmake @@ -70,9 +70,10 @@ elseif (LINUX) QtNetwork QtGui QtCore - qgif - qjpeg - jpeg + jscore +# qgif +# qjpeg +# jpeg fontconfig X11 Xrender diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py index ce2d1e0386..a2ef61c8fd 100644 --- a/indra/cmake/run_build_test.py +++ b/indra/cmake/run_build_test.py @@ -46,6 +46,7 @@ $/LicenseInfo$ import os import sys +import signal import subprocess def main(command, libpath=[], vars={}): @@ -113,6 +114,33 @@ def main(command, libpath=[], vars={}): sys.stdout.flush() return subprocess.call(command) +# swiped from vita, sigh, seems like a Bad Idea to introduce dependency +def translate_rc(rc): + """ + Accept an rc encoded as for subprocess.Popen.returncode: + None means still running + int >= 0 means terminated voluntarily with specified rc + int < 0 means terminated by signal (-rc) + + Return a string explaining the outcome. In case of a signal, try to + name the corresponding symbol from the 'signal' module. + """ + if rc is None: + return "still running" + + if rc >= 0: + return "terminated with rc %s" % rc + + # Negative rc means the child was terminated by signal -rc. + rc = -rc + for attr in dir(signal): + if attr.startswith('SIG') and getattr(signal, attr) == rc: + strc = attr + break + else: + strc = str(rc) + return "terminated by signal %s" % strc + if __name__ == "__main__": from optparse import OptionParser parser = OptionParser(usage="usage: %prog [options] command args...") @@ -140,5 +168,5 @@ if __name__ == "__main__": vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars])) if rc not in (None, 0): print >>sys.stderr, "Failure running: %s" % " ".join(args) - print >>sys.stderr, "Error: %s" % rc + print >>sys.stderr, "Error %s: %s" % (rc, translate_rc(rc)) sys.exit((rc < 0) and 255 or rc) diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/indra/edit-me-to-trigger-new-build.txt diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 48e876429d..36c5b67826 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -54,6 +54,11 @@ static const char USAGE[] = "\n" " -o, --output <file1 .. file2> OR <type>\n" " List of image files to create (assumes same order as for input files)\n" " OR 3 letters file type extension to convert each input file into.\n" +" -load, --load_size <n>\n" +" Portion of the input file to load, in bytes." +" If (load == 0), it will load the whole file." +" If (load == -1), it will load the size relevant to reach the requested discard level (see -d)." +" Only valid for j2c images. Default is 0 (load whole file).\n" " -r, --region <x0, y0, x1, y1>\n" " Crop region applied to the input files in pixels.\n" " Only used for j2c images. Default is no region cropping.\n" @@ -104,22 +109,52 @@ void output_image_stats(LLPointer<LLImageFormatted> image, const std::string &fi // Print out some statistical data on the image std::cout << "Image stats for : " << filename << ", extension : " << image->getExtension() << std::endl; - std::cout << " with : " << (int)(image->getWidth()) << ", height : " << (int)(image->getHeight()) << std::endl; - std::cout << " comp : " << (int)(image->getComponents()) << ", levels : " << (int)(image->getDiscardLevel()) << std::endl; - std::cout << " head : " << (int)(image->calcHeaderSize()) << ", data : " << (int)(image->getDataSize()) << std::endl; + std::cout << " with : " << (int)(image->getWidth()) << ", height : " << (int)(image->getHeight()) << std::endl; + std::cout << " comp : " << (int)(image->getComponents()) << ", levels : " << (int)(image->getLevels()) << std::endl; + std::cout << " head : " << (int)(image->calcHeaderSize()) << ", data : " << (int)(image->getDataSize()) << std::endl; return; } // Load an image from file and return a raw (decompressed) instance of its data -LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, bool output_stats) +LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, int load_size, bool output_stats) { LLPointer<LLImageFormatted> image = create_image(src_filename); - // This just loads the image file stream into a buffer. No decoding done. - if (!image->load(src_filename)) + // We support partial loading only for j2c images + if (image->getCodec() == IMG_CODEC_J2C) { - return NULL; + // Load the header + if (!image->load(src_filename, 600)) + { + return NULL; + } + S32 h = ((LLImageJ2C*)(image.get()))->calcHeaderSize(); + S32 d = (load_size > 0 ? ((LLImageJ2C*)(image.get()))->calcDiscardLevelBytes(load_size) : 0); + S8 r = ((LLImageJ2C*)(image.get()))->getRawDiscardLevel(); + std::cout << "Merov debug : header = " << h << ", load_size = " << load_size << ", discard level = " << d << ", raw discard level = " << r << std::endl; + for (d = 0; d < MAX_DISCARD_LEVEL; d++) + { + S32 data_size = ((LLImageJ2C*)(image.get()))->calcDataSize(d); + std::cout << "Merov debug : discard_level = " << d << ", data_size = " << data_size << std::endl; + } + if (load_size < 0) + { + load_size = (discard_level != -1 ? ((LLImageJ2C*)(image.get()))->calcDataSize(discard_level) : 0); + } + // Load the requested byte range + if (!image->load(src_filename, load_size)) + { + return NULL; + } + } + else + { + // This just loads the image file stream into a buffer. No decoding done. + if (!image->load(src_filename)) + { + return NULL; + } } if( (image->getComponents() != 3) && (image->getComponents() != 4) ) @@ -310,6 +345,7 @@ int main(int argc, char** argv) bool image_stats = false; int* region = NULL; int discard_level = -1; + int load_size = 0; int precincts_size = -1; int blocks_size = -1; int levels = 0; @@ -396,6 +432,22 @@ int main(int argc, char** argv) discard_level = llclamp(discard_level,0,5); } } + else if (!strcmp(argv[arg], "--load_size") || !strcmp(argv[arg], "-load")) + { + std::string value_str; + if ((arg + 1) < argc) + { + value_str = argv[arg+1]; + } + if (((arg + 1) >= argc) || (value_str[0] == '-')) + { + std::cout << "No valid --load_size argument given, load_size ignored" << std::endl; + } + else + { + load_size = atoi(value_str.c_str()); + } + } else if (!strcmp(argv[arg], "--precincts") || !strcmp(argv[arg], "-p")) { std::string value_str; @@ -510,7 +562,7 @@ int main(int argc, char** argv) for (; in_file != in_end; ++in_file, ++out_file) { // Load file - LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, image_stats); + LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, load_size, image_stats); if (!raw_image) { std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt index 1180460f4b..633ad84159 100644 --- a/indra/integration_tests/llui_libtest/CMakeLists.txt +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -18,7 +18,6 @@ include(LLWindow) include(LLUI) include(LLVFS) # ugh, needed for LLDir include(LLXML) -include(LLXUIXML) include(Linking) # include(Tut) @@ -32,7 +31,6 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLXUIXML_INCLUDE_DIRS} ) set(llui_libtest_SOURCE_FILES diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index c33a03034a..a4fb77357c 100644 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -41,6 +41,14 @@ import tarfile import errno import subprocess +class ManifestError(RuntimeError): + """Use an exception more specific than generic Python RuntimeError""" + pass + +class MissingError(ManifestError): + """You specified a file that doesn't exist""" + pass + def path_ancestors(path): drive, path = os.path.splitdrive(os.path.normpath(path)) result = [] @@ -180,6 +188,9 @@ def usage(srctree=""): arg['description'] % nd) def main(): +## import itertools +## print ' '.join((("'%s'" % item) if ' ' in item else item) +## for item in itertools.chain([sys.executable], sys.argv)) option_names = [arg['name'] + '=' for arg in ARGUMENTS] option_names.append('help') options, remainder = getopt.getopt(sys.argv[1:], "", option_names) @@ -385,7 +396,7 @@ class LLManifest(object): child.stdout.close() status = child.wait() if status: - raise RuntimeError( + raise ManifestError( "Command %s returned non-zero status (%s) \noutput:\n%s" % (command, status, output) ) return output @@ -395,7 +406,7 @@ class LLManifest(object): a) verify that you really have created it b) schedule it for cleanup""" if not os.path.exists(path): - raise RuntimeError, "Should be something at path " + path + raise ManifestError, "Should be something at path " + path self.created_paths.append(path) def put_in_file(self, contents, dst): @@ -550,7 +561,7 @@ class LLManifest(object): except (IOError, os.error), why: errors.append((srcname, dstname, why)) if errors: - raise RuntimeError, errors + raise ManifestError, errors def cmakedirs(self, path): @@ -598,11 +609,10 @@ class LLManifest(object): def check_file_exists(self, path): if not os.path.exists(path) and not os.path.islink(path): - raise RuntimeError("Path %s doesn't exist" % ( - os.path.normpath(os.path.join(os.getcwd(), path)),)) + raise MissingError("Path %s doesn't exist" % (os.path.abspath(path),)) - wildcard_pattern = re.compile('\*') + wildcard_pattern = re.compile(r'\*') def expand_globs(self, src, dst): src_list = glob.glob(src) src_re, d_template = self.wildcard_regex(src.replace('\\', '/'), @@ -615,7 +625,7 @@ class LLManifest(object): sys.stdout.write("Processing %s => %s ... " % (src, dst)) sys.stdout.flush() if src == None: - raise RuntimeError("No source file, dst is " + dst) + raise ManifestError("No source file, dst is " + dst) if dst == None: dst = src dst = os.path.join(self.get_dst_prefix(), dst) @@ -637,13 +647,23 @@ class LLManifest(object): else: count += self.process_file(src, dst) return count - try: - count = try_path(os.path.join(self.get_src_prefix(), src)) - except RuntimeError: + + for pfx in self.get_src_prefix(), self.get_artwork_prefix(), self.get_build_prefix(): try: - count = try_path(os.path.join(self.get_artwork_prefix(), src)) - except RuntimeError: - count = try_path(os.path.join(self.get_build_prefix(), src)) + count = try_path(os.path.join(pfx, src)) + except MissingError: + # If src isn't a wildcard, and if that file doesn't exist in + # this pfx, try next pfx. + count = 0 + continue + + # Here try_path() didn't raise MissingError. Did it process any files? + if count: + break + # Even though try_path() didn't raise MissingError, it returned 0 + # files. src is probably a wildcard meant for some other pfx. Loop + # back to try the next. + print "%d files" % count def do(self, *actions): diff --git a/indra/linux_updater/CMakeLists.txt b/indra/linux_updater/CMakeLists.txt index 00a78b2a8f..4377a6333c 100644 --- a/indra/linux_updater/CMakeLists.txt +++ b/indra/linux_updater/CMakeLists.txt @@ -10,14 +10,14 @@ include(UI) include(LLCommon) include(LLVFS) include(LLXML) -include(LLXUIXML) +include(LLUI) include(Linking) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLXUIXML_INCLUDE_DIRS} + ${LLUI_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} ${CARES_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS} @@ -42,7 +42,7 @@ target_link_libraries(linux-updater ${CRYPTO_LIBRARIES} ${UI_LIBRARIES} ${LLXML_LIBRARIES} - ${LLXUIXML_LIBRARIES} + ${LLUI_LIBRARIES} ${LLVFS_LIBRARIES} ${LLCOMMON_LIBRARIES} ) diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp index eed00ac06e..277f0a5367 100644 --- a/indra/linux_updater/linux_updater.cpp +++ b/indra/linux_updater/linux_updater.cpp @@ -1,4 +1,4 @@ -/** +/** * @file linux_updater.cpp * @author Kyle Ambroff <ambroff@lindenlab.com>, Tofu Linden * @brief Viewer update program for unix platforms that support GTK+ @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&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$ */ @@ -34,10 +34,30 @@ #include "llfile.h" #include "lldir.h" #include "lldiriterator.h" + +/*==========================================================================*| +// IQA-490: Use of LLTrans -- by this program at least -- appears to be buggy. +// With it, the 3.3.2 beta 1 linux-updater.bin crashes; without it seems stable. #include "llxmlnode.h" #include "lltrans.h" +|*==========================================================================*/ + +static class LLTrans +{ +public: + LLTrans(); + static std::string getString(const std::string& key); + +private: + std::string _getString(const std::string& key) const; + + typedef std::map<std::string, std::string> MessageMap; + MessageMap mMessages; +} sLLTransInstance; #include <curl/curl.h> +#include <map> +#include <boost/foreach.hpp> extern "C" { #include <gtk/gtk.h> @@ -85,6 +105,8 @@ void init_default_trans_args() bool translate_init(std::string comma_delim_path_list, std::string base_xml_name) { + return true; +/*==========================================================================*| init_default_trans_args(); // extract paths string vector from comma-delimited flat string @@ -112,6 +134,7 @@ bool translate_init(std::string comma_delim_path_list, LLTrans::parseStrings(root, default_trans_args); return true; } +|*==========================================================================*/ } @@ -151,7 +174,7 @@ void updater_app_ui_init(UpdaterAppState *app_state) GTK_WIN_POS_CENTER_ALWAYS); gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12); - g_signal_connect(G_OBJECT(app_state->window), "delete-event", + g_signal_connect(G_OBJECT(app_state->window), "delete-event", G_CALLBACK(on_window_closed), app_state); vbox = gtk_vbox_new(FALSE, 6); @@ -165,7 +188,7 @@ void updater_app_ui_init(UpdaterAppState *app_state) summary_label = gtk_label_new(NULL); gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE); - gtk_label_set_markup(GTK_LABEL(summary_label), + gtk_label_set_markup(GTK_LABEL(summary_label), label_ostr.str().c_str()); gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5); gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0); @@ -195,9 +218,9 @@ void updater_app_ui_init(UpdaterAppState *app_state) // set up progress bar, and update it roughly every 1/10 of a second app_state->progress_bar = gtk_progress_bar_new(); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), + gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str()); - gtk_box_pack_start(GTK_BOX(vbox), + gtk_box_pack_start(GTK_BOX(vbox), app_state->progress_bar, FALSE, TRUE, 0); app_state->progress_update_timeout_id = g_timeout_add (UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state); @@ -299,7 +322,7 @@ gpointer worker_thread_cb(gpointer data) g_error_free(error); throw 0; } - + if(tmp_local_filename != NULL) { app_state->file = tmp_local_filename; @@ -342,7 +365,7 @@ gpointer worker_thread_cb(gpointer data) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE); curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &download_progress_cb); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state); @@ -352,8 +375,8 @@ gpointer worker_thread_cb(gpointer data) if (result) { - llerrs << "Failed to download update: " - << app_state->url + llerrs << "Failed to download update: " + << app_state->url << llendl; gdk_threads_enter(); @@ -365,7 +388,7 @@ gpointer worker_thread_cb(gpointer data) throw 0; } } - + // now pulse the progres bar back and forth while the package is // being unpacked gdk_threads_enter(); @@ -386,8 +409,8 @@ gpointer worker_thread_cb(gpointer data) gdk_threads_enter(); display_error(app_state->window, - LLTrans::getString("UpdaterFailInstallTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); + LLTrans::getString("UpdaterFailInstallTitle"), + LLTrans::getString("UpdaterFailUpdateDescriptive")); //"Failed to update " + app_state->app_name, gdk_threads_leave(); throw 0; @@ -402,8 +425,8 @@ gpointer worker_thread_cb(gpointer data) gdk_threads_enter(); display_error(app_state->window, - LLTrans::getString("UpdaterFailStartTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); + LLTrans::getString("UpdaterFailStartTitle"), + LLTrans::getString("UpdaterFailUpdateDescriptive")); gdk_threads_leave(); throw 0; } @@ -448,7 +471,7 @@ gboolean less_anal_gspawnsync(gchar **argv, // restore SIGCHLD handler sigaction(SIGCHLD, &sigchld_backup, NULL); - + return rtn; } @@ -477,7 +500,7 @@ rename_with_sudo_fallback(const std::string& filename, const std::string& newnam { char *src_string_copy = g_strdup(filename.c_str()); char *dst_string_copy = g_strdup(newname.c_str()); - char* argv[] = + char* argv[] = { sudo_cmd, mv_cmd, @@ -492,8 +515,8 @@ rename_with_sudo_fallback(const std::string& filename, const std::string& newnam if (!less_anal_gspawnsync(argv, &stderr_output, &child_exit_status, &spawn_error)) { - llwarns << "Failed to spawn child process: " - << spawn_error->message + llwarns << "Failed to spawn child process: " + << spawn_error->message << llendl; } else if (child_exit_status) @@ -506,7 +529,7 @@ rename_with_sudo_fallback(const std::string& filename, const std::string& newnam { // everything looks good, clear the error code rtncode = 0; - } + } g_free(src_string_copy); g_free(dst_string_copy); @@ -531,7 +554,7 @@ gboolean install_package(std::string package_file, std::string destination) } llinfos << "Found tar command: " << tar_cmd << llendl; - // Unpack the tarball in a temporary place first, then move it to + // Unpack the tarball in a temporary place first, then move it to // its final destination std::string tmp_dest_dir = gDirUtilp->getTempFilename(); if (LLFile::mkdir(tmp_dest_dir, 0744)) @@ -571,8 +594,8 @@ gboolean install_package(std::string package_file, std::string destination) if (!less_anal_gspawnsync(argv, &stderr_output, &child_exit_status, &untar_error)) { - llwarns << "Failed to spawn child process: " - << untar_error->message + llwarns << "Failed to spawn child process: " + << untar_error->message << llendl; return FALSE; } @@ -605,8 +628,8 @@ gboolean install_package(std::string package_file, std::string destination) if (rename_with_sudo_fallback(destination, backup_dir)) { - llwarns << "Failed to move directory: '" - << destination << "' -> '" << backup_dir + llwarns << "Failed to move directory: '" + << destination << "' -> '" << backup_dir << llendl; return FALSE; } @@ -617,7 +640,7 @@ gboolean install_package(std::string package_file, std::string destination) if (rename_with_sudo_fallback(tmp_dest_dir, destination)) { llwarns << "Failed to move installation to the destination: " - << destination + << destination << llendl; return FALSE; } @@ -713,7 +736,7 @@ BOOL spawn_viewer(UpdaterAppState *app_state) if (!success) { - llwarns << "Failed to launch viewer: " << error->message + llwarns << "Failed to launch viewer: " << error->message << llendl; } @@ -751,7 +774,7 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state) else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc)) { app_state->image_dir = argv[i]; - app_state->image_dir_iter = new LLDirIterator(argv[i], "/*.jpg"); + app_state->image_dir_iter = new LLDirIterator(argv[i], "*.jpg"); } else if ((!strcmp(argv[i], "--dest")) && (++i < argc)) { @@ -772,8 +795,8 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state) } } - if (app_state->app_name.empty() - || (app_state->url.empty() && app_state->file.empty()) + if (app_state->app_name.empty() + || (app_state->url.empty() && app_state->file.empty()) || app_state->dest_dir.empty()) { show_usage_and_exit(); @@ -799,7 +822,7 @@ int main(int argc, char **argv) (gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); std::string old_log_file = gDirUtilp->getExpandedFilename (LL_PATH_LOGS, "updater.log.old"); - std::string log_file = + std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); LLFile::rename(log_file, old_log_file); LLError::logToFile(log_file); @@ -841,3 +864,63 @@ int main(int argc, char **argv) return success ? 0 : 1; } +/***************************************************************************** +* Dummy LLTrans implementation (IQA-490) +*****************************************************************************/ +static LLTrans sStaticStrings; + +// lookup +std::string LLTrans::_getString(const std::string& key) const +{ + MessageMap::const_iterator found = mMessages.find(key); + if (found != mMessages.end()) + { + return found->second; + } + LL_WARNS("linux_updater") << "No message for key '" << key + << "' -- add to LLTrans::LLTrans() in linux_updater.cpp" + << LL_ENDL; + return key; +} + +// static lookup +std::string LLTrans::getString(const std::string& key) +{ + return sLLTransInstance._getString(key); +} + +// initialization +LLTrans::LLTrans() +{ + typedef std::pair<const char*, const char*> Pair; + static const Pair data[] = + { + Pair("UpdaterFailDownloadTitle", + "Failed to download update"), + Pair("UpdaterFailInstallTitle", + "Failed to install update"), + Pair("UpdaterFailStartTitle", + "Failed to start viewer"), + Pair("UpdaterFailUpdateDescriptive", + "An error occurred while updating Second Life. " + "Please download the latest version from www.secondlife.com."), + Pair("UpdaterNowInstalling", + "Installing Second Life..."), + Pair("UpdaterNowUpdating", + "Now updating Second Life..."), + Pair("UpdaterProgressBarText", + "Downloading update"), + Pair("UpdaterProgressBarTextWithEllipses", + "Downloading update..."), + Pair("UpdaterUpdatingDescriptive", + "Your Second Life Viewer is being updated to the latest release. " + "This may take some time, so please be patient."), + Pair("UpdaterWindowTitle", + "Second Life Update") + }; + + BOOST_FOREACH(Pair pair, data) + { + mMessages[pair.first] = pair.second; + } +} diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index f0b44f97d2..6c97a64ed7 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -215,7 +215,7 @@ BOOL LLVorbisDecodeState::initDecode() return(FALSE); } - S32 sample_count = ov_pcm_total(&mVF, -1); + S32 sample_count = (S32)ov_pcm_total(&mVF, -1); size_t size_guess = (size_t)sample_count; vorbis_info* vi = ov_info(&mVF, -1); size_guess *= (vi? vi->channels : 1); @@ -571,7 +571,8 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) llwarns << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << llendl; mCurrentDecodep->flushBadFile(); LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); - adp->setHasValidData(FALSE); + adp->setHasValidData(false); + adp->setHasCompletedDecode(true); mCurrentDecodep = NULL; done = TRUE; } @@ -586,11 +587,16 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) if (mCurrentDecodep->finishDecode()) { // We finished! - if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone()) + LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); + if (!adp) { - LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); - adp->setHasDecodedData(TRUE); - adp->setHasValidData(TRUE); + llwarns << "Missing LLAudioData for decode of " << mCurrentDecodep->getUUID() << llendl; + } + else if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone()) + { + adp->setHasCompletedDecode(true); + adp->setHasDecodedData(true); + adp->setHasValidData(true); // At this point, we could see if anyone needs this sound immediately, but // I'm not sure that there's a reason to - we need to poll all of the playing @@ -599,7 +605,8 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) } else { - llinfos << "Vorbis decode failed!!!" << llendl; + adp->setHasCompletedDecode(true); + llinfos << "Vorbis decode failed for " << mCurrentDecodep->getUUID() << llendl; } mCurrentDecodep = NULL; } @@ -667,16 +674,19 @@ BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid) if (gAudiop->hasDecodedFile(uuid)) { // Already have a decoded version, don't need to decode it. + //llinfos << "addDecodeRequest for " << uuid << " has decoded file already" << llendl; return TRUE; } if (gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) { // Just put it on the decode queue. + //llinfos << "addDecodeRequest for " << uuid << " has local asset file already" << llendl; mImpl->mDecodeQueue.push(uuid); return TRUE; } + //llinfos << "addDecodeRequest for " << uuid << " no file available" << llendl; return FALSE; } diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 5fa28cb902..72c0091d17 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -1221,10 +1221,11 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E // Need to mark data as bad to avoid constant rerequests. LLAudioData *adp = gAudiop->getAudioData(uuid); if (adp) - { + { // Make sure everything is cleared adp->setHasValidData(false); adp->setHasLocalData(false); adp->setHasDecodedData(false); + adp->setHasCompletedDecode(true); } } else @@ -1237,6 +1238,7 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E } else { + // llinfos << "Got asset callback with good audio data for " << uuid << ", making decode request" << llendl; adp->setHasValidData(true); adp->setHasLocalData(true); gAudioDecodeMgrp->addDecodeRequest(uuid); @@ -1304,16 +1306,18 @@ void LLAudioSource::update() if (!getCurrentBuffer()) { - if (getCurrentData()) + LLAudioData *adp = getCurrentData(); + if (adp) { // Hack - try and load the sound. Will do this as a callback // on decode later. - if (getCurrentData()->load() && getCurrentData()->getBuffer()) + if (adp->load() && adp->getBuffer()) { - play(getCurrentData()->getID()); + play(adp->getID()); } - else + else if (adp->hasCompletedDecode()) // Only mark corrupted after decode is done { + llwarns << "Marking LLAudioSource corrupted for " << adp->getID() << llendl; mCorrupted = true ; } } @@ -1731,6 +1735,7 @@ LLAudioData::LLAudioData(const LLUUID &uuid) : mBufferp(NULL), mHasLocalData(false), mHasDecodedData(false), + mHasCompletedDecode(false), mHasValidData(true) { if (uuid.isNull()) @@ -1742,12 +1747,13 @@ LLAudioData::LLAudioData(const LLUUID &uuid) : if (gAudiop && gAudiop->hasDecodedFile(uuid)) { // Already have a decoded version, don't need to decode it. - mHasLocalData = true; - mHasDecodedData = true; + setHasLocalData(true); + setHasDecodedData(true); + setHasCompletedDecode(true); } else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) { - mHasLocalData = true; + setHasLocalData(true); } } diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index a47ee7ca7c..df1e4dc305 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -37,6 +37,7 @@ #include "lluuid.h" #include "llframetimer.h" #include "llassettype.h" +#include "llextendedstatus.h" #include "lllistener.h" @@ -371,10 +372,12 @@ public: bool hasLocalData() const { return mHasLocalData; } bool hasDecodedData() const { return mHasDecodedData; } + bool hasCompletedDecode() const { return mHasCompletedDecode; } bool hasValidData() const { return mHasValidData; } void setHasLocalData(const bool hld) { mHasLocalData = hld; } void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; } + void setHasCompletedDecode(const bool hcd) { mHasCompletedDecode = hcd; } void setHasValidData(const bool hvd) { mHasValidData = hvd; } friend class LLAudioEngine; // Severe laziness, bad. @@ -382,9 +385,10 @@ public: protected: LLUUID mID; LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here. - bool mHasLocalData; - bool mHasDecodedData; - bool mHasValidData; + bool mHasLocalData; // Set true if the sound asset file is available locally + bool mHasDecodedData; // Set true if the sound file has been decoded + bool mHasCompletedDecode; // Set true when the sound is decoded + bool mHasValidData; // Set false if decoding failed, meaning the sound asset is bad }; diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index f3cf950afa..2a0df26384 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -1570,7 +1570,7 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp) constraint_it++) { U8 byte = constraint_it->mChainLength; - dp.packU8(byte, "chain_lenght"); + dp.packU8(byte, "chain_length"); byte = constraint_it->mConstraintType; dp.packU8(byte, "constraint_type"); diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index e81a27c2bc..3ebb2bffb0 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -126,7 +126,7 @@ public: virtual void addDebugText( const std::string& text ) = 0; - virtual const LLUUID& getID() = 0; + virtual const LLUUID& getID() const = 0; //------------------------------------------------------------------------- // End Interface //------------------------------------------------------------------------- diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 0a3eaec5c5..dd7b8c6eb8 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -61,7 +61,10 @@ set(llcommon_SOURCE_FILES llformat.cpp llframetimer.cpp llheartbeat.cpp + llinitparam.cpp llinstancetracker.cpp + llleap.cpp + llleaplistener.cpp llliveappconfig.cpp lllivefile.cpp lllog.cpp @@ -74,13 +77,14 @@ set(llcommon_SOURCE_FILES llmortician.cpp lloptioninterface.cpp llptrto.cpp - llprocesslauncher.cpp + llprocess.cpp llprocessor.cpp llqueuedthread.cpp llrand.cpp llrefcount.cpp llrun.cpp llsd.cpp + llsdparam.cpp llsdserialize.cpp llsdserialize_xml.cpp llsdutil.cpp @@ -88,6 +92,7 @@ set(llcommon_SOURCE_FILES llsingleton.cpp llstat.cpp llstacktrace.cpp + llstreamqueue.cpp llstreamtools.cpp llstring.cpp llstringtable.cpp @@ -173,9 +178,12 @@ set(llcommon_HEADER_FILES llheartbeat.h llhttpstatuscodes.h llindexedqueue.h + llinitparam.h llinstancetracker.h llkeythrottle.h lllazy.h + llleap.h + llleaplistener.h lllistenerwrapper.h lllinkedqueue.h llliveappconfig.h @@ -196,7 +204,7 @@ set(llcommon_HEADER_FILES llpointer.h llpreprocessor.h llpriqueuemap.h - llprocesslauncher.h + llprocess.h llprocessor.h llptrskiplist.h llptrskipmap.h @@ -204,10 +212,12 @@ set(llcommon_HEADER_FILES llqueuedthread.h llrand.h llrefcount.h + llregistry.h llrun.h llrefcount.h llsafehandle.h llsd.h + llsdparam.h llsdserialize.h llsdserialize_xml.h llsdutil.h @@ -216,11 +226,13 @@ set(llcommon_HEADER_FILES llsingleton.h llskiplist.h llskipmap.h + llsortedvector.h llstack.h llstacktrace.h llstat.h llstatenums.h llstl.h + llstreamqueue.h llstreamtools.h llstrider.h llstring.h @@ -230,6 +242,7 @@ set(llcommon_HEADER_FILES llthreadsafequeue.h lltimer.h lltreeiterators.h + lltypeinfolookup.h lluri.h lluuid.h lluuidhashmap.h @@ -317,8 +330,7 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") - LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}" - "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py") + LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") @@ -326,6 +338,9 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}") LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}") # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index bdcc98e402..5cfcdab41c 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -52,34 +52,11 @@ #include <ctime> #include <iosfwd> -// Work around Microsoft compiler warnings in STL headers -#ifdef LL_WINDOWS -#pragma warning (disable : 4702) // unreachable code -#pragma warning (disable : 4244) // conversion from time_t to S32 -#endif // LL_WINDOWS - -// *TODO: Eliminate these, most library .cpp files don't need them. -// Add them to llviewerprecompiledheaders.h if necessary. -#include <list> -#include <map> -#include <vector> -#include <string> - -#ifdef LL_WINDOWS -// Reenable warnings we disabled above -#pragma warning (3 : 4702) // unreachable code, we like level 3, not 4 -// moved msvc warnings to llpreprocessor.h *TODO - delete this comment after merge conflicts are unlikely -brad -#endif // LL_WINDOWS - // Linden only libs in alpha-order other than stdtypes.h // *NOTE: Please keep includes here to a minimum, see above. #include "stdtypes.h" #include "lldefs.h" #include "llerror.h" -#include "llextendedstatus.h" -// Don't do this, adds 15K lines of header code to every library file. -//#include "llfasttimer.h" #include "llfile.h" -#include "llformat.h" #endif diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index ba3dd6d6b4..3206843bf4 100644 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -106,6 +106,11 @@ std::string LLAvatarName::getCompleteName() const std::string LLAvatarName::getLegacyName() const { + if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled? + { + return mDisplayName; + } + std::string name; name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() ); name = mLegacyFirstName; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index e4381dbbd6..7e6eee0f3c 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -654,9 +654,7 @@ namespace LLError g.invalidateCallSites(); s.tagLevelMap[tag_name] = level; } -} -namespace { LLError::ELevel decodeLevel(std::string name) { static LevelMap level_names; @@ -681,7 +679,9 @@ namespace { return i->second; } - +} + +namespace { void setLevels(LevelMap& map, const LLSD& list, LLError::ELevel level) { LLSD::array_const_iterator i, end; diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index ed9de002f5..d53a819d88 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -1,4 +1,4 @@ -/** +/** * @file llerrorcontrol.h * @date December 2006 * @brief error message system control @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,7 +38,7 @@ class LLSD; This is the part of the LLError namespace that manages the messages produced by the logging. The logging support is defined in llerror.h. Most files do not need to include this. - + These implementations are in llerror.cpp. */ @@ -72,7 +72,7 @@ namespace LLError Settings that control what is logged. Setting a level means log messages at that level or above. */ - + LL_COMMON_API void setPrintLocation(bool); LL_COMMON_API void setDefaultLevel(LLError::ELevel); LL_COMMON_API ELevel getDefaultLevel(); @@ -80,7 +80,8 @@ namespace LLError LL_COMMON_API void setClassLevel(const std::string& class_name, LLError::ELevel); LL_COMMON_API void setFileLevel(const std::string& file_name, LLError::ELevel); LL_COMMON_API void setTagLevel(const std::string& file_name, LLError::ELevel); - + + LL_COMMON_API LLError::ELevel decodeLevel(std::string name); LL_COMMON_API void configure(const LLSD&); // the LLSD can configure all of the settings // usually read automatically from the live errorlog.xml file @@ -100,31 +101,31 @@ namespace LLError // (by, for example, setting a class level to LEVEL_NONE), will keep // the that message from causing the fatal funciton to be invoked. - LL_COMMON_API FatalFunction getFatalFunction(); - // Retrieve the previously-set FatalFunction - - /// temporarily override the FatalFunction for the duration of a - /// particular scope, e.g. for unit tests - class LL_COMMON_API OverrideFatalFunction - { - public: - OverrideFatalFunction(const FatalFunction& func): - mPrev(getFatalFunction()) - { - setFatalFunction(func); - } - ~OverrideFatalFunction() - { - setFatalFunction(mPrev); - } - - private: - FatalFunction mPrev; - }; + LL_COMMON_API FatalFunction getFatalFunction(); + // Retrieve the previously-set FatalFunction + + /// temporarily override the FatalFunction for the duration of a + /// particular scope, e.g. for unit tests + class LL_COMMON_API OverrideFatalFunction + { + public: + OverrideFatalFunction(const FatalFunction& func): + mPrev(getFatalFunction()) + { + setFatalFunction(func); + } + ~OverrideFatalFunction() + { + setFatalFunction(mPrev); + } + + private: + FatalFunction mPrev; + }; typedef std::string (*TimeFunction)(); LL_COMMON_API std::string utcTime(); - + LL_COMMON_API void setTimeFunction(TimeFunction); // The function is use to return the current time, formatted for // display by those error recorders that want the time included. @@ -136,19 +137,27 @@ namespace LLError // An object that handles the actual output or error messages. public: virtual ~Recorder(); - + virtual void recordMessage(LLError::ELevel, const std::string& message) = 0; // use the level for better display, not for filtering - + virtual bool wantsTime(); // default returns false // override and return true if the recorder wants the time string // included in the text of the message }; - + + /** + * @NOTE: addRecorder() conveys ownership to the underlying Settings + * object -- when destroyed, it will @em delete the passed Recorder*! + */ LL_COMMON_API void addRecorder(Recorder*); + /** + * @NOTE: removeRecorder() reclaims ownership of the Recorder*: its + * lifespan becomes the caller's problem. + */ LL_COMMON_API void removeRecorder(Recorder*); // each error message is passed to each recorder via recordMessage() - + LL_COMMON_API void logToFile(const std::string& filename); LL_COMMON_API void logToFixedBuffer(LLLineBuffer*); // Utilities to add recorders for logging to a file or a fixed buffer @@ -166,10 +175,9 @@ namespace LLError class Settings; LL_COMMON_API Settings* saveAndResetSettings(); LL_COMMON_API void restoreSettings(Settings *); - + LL_COMMON_API std::string abbreviateFile(const std::string& filePath); LL_COMMON_API int shouldLogCallCount(); - }; #endif // LL_LLERRORCONTROL_H diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp index 902eaa3b72..950fcd6e83 100644 --- a/indra/llcommon/llerrorthread.cpp +++ b/indra/llcommon/llerrorthread.cpp @@ -112,13 +112,8 @@ void LLErrorThread::run() #if !LL_WINDOWS U32 last_sig_child_count = 0; #endif - while (1) + while (! (LLApp::isError() || LLApp::isStopped())) { - if (LLApp::isError() || LLApp::isStopped()) - { - // The application has stopped running, time to take action (maybe) - break; - } #if !LL_WINDOWS // Check whether or not the main thread had a sig child we haven't handled. U32 current_sig_child_count = LLApp::getSigChildCount(); diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index db1ea4792b..0855180dcd 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -430,13 +430,13 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL { // The new node isn't last. Place it between the previous node and // the successor. - newNode = (myprev + mydmi->second)/2.0; + newNode = (myprev + mydmi->second)/2.f; } else { // The new node is last. Bump myprev up to the next integer, add // 1.0 and use that. - newNode = std::ceil(myprev) + 1.0; + newNode = std::ceil(myprev) + 1.f; } // Now that newNode has a value that places it appropriately in mSignal, // connect it. diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index c32a776c3f..c51d042a3d 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llfile.cpp * @author Michael Schlachter * @date 2006-03-23 @@ -8,60 +8,194 @@ * $LicenseInfo:firstyear=2006&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$ */ #if LL_WINDOWS #include <windows.h> +#include <stdlib.h> // Windows errno +#else +#include <errno.h> #endif #include "linden_common.h" #include "llfile.h" #include "llstring.h" #include "llerror.h" +#include "stringize.h" using namespace std; +static std::string empty; + +// Many of the methods below use OS-level functions that mess with errno. Wrap +// variants of strerror() to report errors. + +#if LL_WINDOWS +// On Windows, use strerror_s(). +std::string strerr(int errn) +{ + char buffer[256]; + strerror_s(buffer, errn); // infers sizeof(buffer) -- love it! + return buffer; +} + +#else +// On Posix we want to call strerror_r(), but alarmingly, there are two +// different variants. The one that returns int always populates the passed +// buffer (except in case of error), whereas the other one always returns a +// valid char* but might or might not populate the passed buffer. How do we +// know which one we're getting? Define adapters for each and let the compiler +// select the applicable adapter. + +// strerror_r() returns char* +std::string message_from(int /*orig_errno*/, const char* /*buffer*/, size_t /*bufflen*/, + const char* strerror_ret) +{ + return strerror_ret; +} + +// strerror_r() returns int +std::string message_from(int orig_errno, const char* buffer, size_t bufflen, + int strerror_ret) +{ + if (strerror_ret == 0) + { + return buffer; + } + // Here strerror_r() has set errno. Since strerror_r() has already failed, + // seems like a poor bet to call it again to diagnose its own error... + int stre_errno = errno; + if (stre_errno == ERANGE) + { + return STRINGIZE("strerror_r() can't explain errno " << orig_errno + << " (" << bufflen << "-byte buffer too small)"); + } + if (stre_errno == EINVAL) + { + return STRINGIZE("unknown errno " << orig_errno); + } + // Here we don't even understand the errno from strerror_r()! + return STRINGIZE("strerror_r() can't explain errno " << orig_errno + << " (error " << stre_errno << ')'); +} + +std::string strerr(int errn) +{ + char buffer[256]; + // Select message_from() function matching the strerror_r() we have on hand. + return message_from(errn, buffer, sizeof(buffer), + strerror_r(errn, buffer, sizeof(buffer))); +} +#endif // ! LL_WINDOWS + +// On either system, shorthand call just infers global 'errno'. +std::string strerr() +{ + return strerr(errno); +} + +int warnif(const std::string& desc, const std::string& filename, int rc, int accept=0) +{ + if (rc < 0) + { + // Capture errno before we start emitting output + int errn = errno; + // For certain operations, a particular errno value might be + // acceptable -- e.g. stat() could permit ENOENT, mkdir() could permit + // EEXIST. Don't warn if caller explicitly says this errno is okay. + if (errn != accept) + { + LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename + << "' (errno " << errn << "): " << strerr(errn) << LL_ENDL; + } +#if 0 && LL_WINDOWS // turn on to debug file-locking problems + // If the problem is "Permission denied," maybe it's because another + // process has the file open. Try to find out. + if (errn == EACCES) // *not* EPERM + { + // Only do any of this stuff (before LL_ENDL) if it will be logged. + LL_DEBUGS("LLFile") << empty; + const char* TEMP = getenv("TEMP"); + if (! TEMP) + { + LL_CONT << "No $TEMP, not running 'handle'"; + } + else + { + std::string tf(TEMP); + tf += "\\handle.tmp"; + // http://technet.microsoft.com/en-us/sysinternals/bb896655 + std::string cmd(STRINGIZE("handle \"" << filename + // "openfiles /query /v | fgrep -i \"" << filename + << "\" > \"" << tf << '"')); + LL_CONT << cmd; + if (system(cmd.c_str()) != 0) + { + LL_CONT << "\nDownload 'handle.exe' from http://technet.microsoft.com/en-us/sysinternals/bb896655"; + } + else + { + std::ifstream inf(tf); + std::string line; + while (std::getline(inf, line)) + { + LL_CONT << '\n' << line; + } + } + LLFile::remove(tf); + } + LL_CONT << LL_ENDL; + } +#endif // LL_WINDOWS hack to identify processes holding file open + } + return rc; +} + // static int LLFile::mkdir(const std::string& dirname, int perms) { -#if LL_WINDOWS +#if LL_WINDOWS // permissions are ignored on Windows std::string utf8dirname = dirname; llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname); - return _wmkdir(utf16dirname.c_str()); + int rc = _wmkdir(utf16dirname.c_str()); #else - return ::mkdir(dirname.c_str(), (mode_t)perms); + int rc = ::mkdir(dirname.c_str(), (mode_t)perms); #endif + // We often use mkdir() to ensure the existence of a directory that might + // already exist. Don't spam the log if it does. + return warnif("mkdir", dirname, rc, EEXIST); } // static int LLFile::rmdir(const std::string& dirname) { -#if LL_WINDOWS +#if LL_WINDOWS // permissions are ignored on Windows std::string utf8dirname = dirname; llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname); - return _wrmdir(utf16dirname.c_str()); + int rc = _wrmdir(utf16dirname.c_str()); #else - return ::rmdir(dirname.c_str()); + int rc = ::rmdir(dirname.c_str()); #endif + return warnif("rmdir", dirname, rc); } // static @@ -108,10 +242,11 @@ int LLFile::remove(const std::string& filename) #if LL_WINDOWS std::string utf8filename = filename; llutf16string utf16filename = utf8str_to_utf16str(utf8filename); - return _wremove(utf16filename.c_str()); + int rc = _wremove(utf16filename.c_str()); #else - return ::remove(filename.c_str()); + int rc = ::remove(filename.c_str()); #endif + return warnif("remove", filename, rc); } int LLFile::rename(const std::string& filename, const std::string& newname) @@ -121,10 +256,11 @@ int LLFile::rename(const std::string& filename, const std::string& newname) std::string utf8newname = newname; llutf16string utf16filename = utf8str_to_utf16str(utf8filename); llutf16string utf16newname = utf8str_to_utf16str(utf8newname); - return _wrename(utf16filename.c_str(),utf16newname.c_str()); + int rc = _wrename(utf16filename.c_str(),utf16newname.c_str()); #else - return ::rename(filename.c_str(),newname.c_str()); + int rc = ::rename(filename.c_str(),newname.c_str()); #endif + return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc); } int LLFile::stat(const std::string& filename, llstat* filestatus) @@ -132,23 +268,26 @@ int LLFile::stat(const std::string& filename, llstat* filestatus) #if LL_WINDOWS std::string utf8filename = filename; llutf16string utf16filename = utf8str_to_utf16str(utf8filename); - return _wstat(utf16filename.c_str(),filestatus); + int rc = _wstat(utf16filename.c_str(),filestatus); #else - return ::stat(filename.c_str(),filestatus); + int rc = ::stat(filename.c_str(),filestatus); #endif + // We use stat() to determine existence (see isfile(), isdir()). + // Don't spam the log if the subject pathname doesn't exist. + return warnif("stat", filename, rc, ENOENT); } bool LLFile::isdir(const std::string& filename) { llstat st; - + return stat(filename, &st) == 0 && S_ISDIR(st.st_mode); } bool LLFile::isfile(const std::string& filename) { llstat st; - + return stat(filename, &st) == 0 && S_ISREG(st.st_mode); } @@ -260,7 +399,7 @@ void llifstream::open(const std::string& _Filename, /* Flawfinder: ignore */ ios_base::openmode _Mode, int _Prot) { // open a C stream with specified mode - + LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot); if(filep == NULL) { @@ -280,7 +419,7 @@ bool llifstream::is_open() const return false; } llifstream::~llifstream() -{ +{ if (_ShouldClose) { close(); @@ -309,7 +448,7 @@ bool llofstream::is_open() const void llofstream::open(const std::string& _Filename, /* Flawfinder: ignore */ ios_base::openmode _Mode, - int _Prot) + int _Prot) { // open a C stream with specified mode LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot); @@ -340,14 +479,14 @@ void llofstream::close() llofstream::llofstream(const std::string& _Filename, std::ios_base::openmode _Mode, - int _Prot) + int _Prot) : std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) { // construct with named file and specified mode open(_Filename, _Mode , _Prot); /* Flawfinder: ignore */ } llofstream::~llofstream() -{ +{ // destroy the object if (_ShouldClose) { diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index db72aa19b9..db72aa19b9 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp diff --git a/indra/llxuixml/llinitparam.h b/indra/llcommon/llinitparam.h index ab20957760..99983a19cb 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -35,6 +35,7 @@ #include <boost/shared_ptr.hpp> #include "llerror.h" +#include "lltypeinfolookup.h" namespace LLInitParam { @@ -205,7 +206,7 @@ namespace LLInitParam mutable std::string mValueName; }; - class Parser + class LL_COMMON_API Parser { LOG_CLASS(Parser); @@ -227,9 +228,9 @@ namespace LLInitParam typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&); typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)> parser_inspect_func_t; - typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID> parser_read_func_map_t; - typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID> parser_write_func_map_t; - typedef std::map<const std::type_info*, parser_inspect_func_t, CompareTypeID> parser_inspect_func_map_t; + typedef LLTypeInfoLookup<parser_read_func_t> parser_read_func_map_t; + typedef LLTypeInfoLookup<parser_write_func_t> parser_write_func_map_t; + typedef LLTypeInfoLookup<parser_inspect_func_t> parser_inspect_func_map_t; Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map) : mParseSilently(false), @@ -301,7 +302,7 @@ namespace LLInitParam class Param; // various callbacks and constraints associated with an individual param - struct ParamDescriptor + struct LL_COMMON_API ParamDescriptor { struct UserData { @@ -341,7 +342,7 @@ namespace LLInitParam typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr; // each derived Block class keeps a static data structure maintaining offsets to various params - class BlockDescriptor + class LL_COMMON_API BlockDescriptor { public: BlockDescriptor(); @@ -369,7 +370,7 @@ namespace LLInitParam class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; - class BaseBlock + class LL_COMMON_API BaseBlock { public: //TODO: implement in terms of owned_ptr @@ -566,7 +567,7 @@ namespace LLInitParam static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); } }; - class Param + class LL_COMMON_API Param { public: void setProvided(bool is_provided = true) @@ -1253,15 +1254,16 @@ namespace LLInitParam return mValues.back(); } - void add(const value_t& item) + self_t& add(const value_t& item) { param_value_t param_value; param_value.setValue(item); mValues.push_back(param_value); setProvided(); + return *this; } - void add(const typename name_value_lookup_t::name_t& name) + self_t& add(const typename name_value_lookup_t::name_t& name) { value_t value; @@ -1271,6 +1273,8 @@ namespace LLInitParam add(value); mValues.back().setValueName(name); } + + return *this; } // implicit conversion @@ -1441,13 +1445,14 @@ namespace LLInitParam return mValues.back(); } - void add(const value_t& item) + self_t& add(const value_t& item) { mValues.push_back(item); setProvided(); + return *this; } - void add(const typename name_value_lookup_t::name_t& name) + self_t& add(const typename name_value_lookup_t::name_t& name) { value_t value; @@ -1457,6 +1462,7 @@ namespace LLInitParam add(value); mValues.back().setValueName(name); } + return *this; } // implicit conversion @@ -2057,8 +2063,8 @@ namespace LLInitParam // block param interface - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; + LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); + LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { //TODO: implement LLSD params as schema type Any diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 34d841a4e0..403df08990 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -167,8 +167,9 @@ public: static T* getInstance(const KEY& k) { - typename InstanceMap::const_iterator found = getMap_().find(k); - return (found == getMap_().end()) ? NULL : found->second; + const InstanceMap& map(getMap_()); + typename InstanceMap::const_iterator found = map.find(k); + return (found == map.end()) ? NULL : found->second; } static instance_iter beginInstances() @@ -239,8 +240,20 @@ class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase public: - /// for completeness of analogy with the generic implementation - static T* getInstance(T* k) { return k; } + /** + * Does a particular instance still exist? Of course, if you already have + * a T* in hand, you need not call getInstance() to @em locate the + * instance -- unlike the case where getInstance() accepts some kind of + * key. Nonetheless this method is still useful to @em validate a + * particular T*, since each instance's destructor removes itself from the + * underlying set. + */ + static T* getInstance(T* k) + { + const InstanceSet& set(getSet_()); + typename InstanceSet::const_iterator found = set.find(k); + return (found == set.end())? NULL : *found; + } static S32 instanceCount() { return getSet_().size(); } class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag> diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp new file mode 100644 index 0000000000..0a57ef1c48 --- /dev/null +++ b/indra/llcommon/llleap.cpp @@ -0,0 +1,459 @@ +/** + * @file llleap.cpp + * @author Nat Goodspeed + * @date 2012-02-20 + * @brief Implementation for llleap. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llleap.h" +// STL headers +#include <sstream> +#include <algorithm> +// std headers +// external library headers +#include <boost/bind.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/tokenizer.hpp> +// other Linden headers +#include "llerror.h" +#include "llstring.h" +#include "llprocess.h" +#include "llevents.h" +#include "stringize.h" +#include "llsdutil.h" +#include "llsdserialize.h" +#include "llerrorcontrol.h" +#include "lltimer.h" +#include "lluuid.h" +#include "llleaplistener.h" + +#if LL_MSVC +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif + +LLLeap::LLLeap() {} +LLLeap::~LLLeap() {} + +class LLLeapImpl: public LLLeap +{ + LOG_CLASS(LLLeap); +public: + // Called only by LLLeap::create() + LLLeapImpl(const std::string& desc, const std::vector<std::string>& plugin): + // We might reassign mDesc in the constructor body if it's empty here. + mDesc(desc), + // We expect multiple LLLeapImpl instances. Definitely tweak + // mDonePump's name for uniqueness. + mDonePump("LLLeap", true), + // Troubling thought: what if one plugin intentionally messes with + // another plugin? LLEventPump names are in a single global namespace. + // Try to make that more difficult by generating a UUID for the reply- + // pump name -- so it should NOT need tweaking for uniqueness. + mReplyPump(LLUUID::generateNewID().asString()), + mExpect(0), + mPrevFatalFunction(LLError::getFatalFunction()), + // Instantiate a distinct LLLeapListener for this plugin. (Every + // plugin will want its own collection of managed listeners, etc.) + // Pass it a callback to our connect() method, so it can send events + // from a particular LLEventPump to the plugin without having to know + // this class or method name. + mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2))) + { + // Rule out empty vector + if (plugin.empty()) + { + throw Error("no plugin command"); + } + + // Don't leave desc empty either, but in this case, if we weren't + // given one, we'll fake one. + if (desc.empty()) + { + mDesc = LLProcess::basename(plugin[0]); + // how about a toLower() variant that returns the transformed string?! + std::string desclower(mDesc); + LLStringUtil::toLower(desclower); + // If we're running a Python script, use the script name for the + // desc instead of just 'python'. Arguably we should check for + // more different interpreters as well, but there's a reason to + // notice Python specially: we provide Python LLSD serialization + // support, so there's a pretty good reason to implement plugins + // in that language. + if (plugin.size() >= 2 && (desclower == "python" || desclower == "python.exe")) + { + mDesc = LLProcess::basename(plugin[1]); + } + } + + // Listen for child "termination" right away to catch launch errors. + mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::bad_launch, this, _1)); + + // Okay, launch child. + LLProcess::Params params; + params.desc = mDesc; + std::vector<std::string>::const_iterator pi(plugin.begin()), pend(plugin.end()); + params.executable = *pi++; + for ( ; pi != pend; ++pi) + { + params.args.add(*pi); + } + params.files.add(LLProcess::FileParam("pipe")); // stdin + params.files.add(LLProcess::FileParam("pipe")); // stdout + params.files.add(LLProcess::FileParam("pipe")); // stderr + params.postend = mDonePump.getName(); + mChild = LLProcess::create(params); + // If that didn't work, no point in keeping this LLLeap object. + if (! mChild) + { + throw Error(STRINGIZE("failed to run " << mDesc)); + } + + // Okay, launch apparently worked. Change our mDonePump listener. + mDonePump.stopListening("LLLeap"); + mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::done, this, _1)); + + // Child might pump large volumes of data through either stdout or + // stderr. Don't bother copying all that data into notification event. + LLProcess::ReadPipe + &childout(mChild->getReadPipe(LLProcess::STDOUT)), + &childerr(mChild->getReadPipe(LLProcess::STDERR)); + childout.setLimit(20); + childerr.setLimit(20); + + // Serialize any event received on mReplyPump to our child's stdin. + mStdinConnection = connect(mReplyPump, "LLLeap"); + + // Listening on stdout is stateful. In general, we're either waiting + // for the length prefix or waiting for the specified length of data. + // We address that with two different listener methods -- one of which + // is blocked at any given time. + mStdoutConnection = childout.getPump() + .listen("prefix", boost::bind(&LLLeapImpl::rstdout, this, _1)); + mStdoutDataConnection = childout.getPump() + .listen("data", boost::bind(&LLLeapImpl::rstdoutData, this, _1)); + mBlocker.reset(new LLEventPump::Blocker(mStdoutDataConnection)); + + // Log anything sent up through stderr. When a typical program + // encounters an error, it writes its error message to stderr and + // terminates with nonzero exit code. In particular, the Python + // interpreter behaves that way. More generally, though, a plugin + // author can log whatever s/he wants to the viewer log using stderr. + mStderrConnection = childerr.getPump() + .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1)); + + // For our lifespan, intercept any LL_ERRS so we can notify plugin + LLError::setFatalFunction(boost::bind(&LLLeapImpl::fatalFunction, this, _1)); + + // Send child a preliminary event reporting our own reply-pump name -- + // which would otherwise be pretty tricky to guess! + wstdin(mReplyPump.getName(), + LLSDMap + ("command", mListener->getName()) + // Include LLLeap features -- this may be important for child to + // construct (or recognize) current protocol. + ("features", LLLeapListener::getFeatures())); + } + + // Normally we'd expect to arrive here only via done() + virtual ~LLLeapImpl() + { + LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL; + // Restore original FatalFunction + LLError::setFatalFunction(mPrevFatalFunction); + } + + // Listener for failed launch attempt + bool bad_launch(const LLSD& data) + { + LL_WARNS("LLLeap") << data["string"].asString() << LL_ENDL; + return false; + } + + // Listener for child-process termination + bool done(const LLSD& data) + { + // Log the termination + LL_INFOS("LLLeap") << data["string"].asString() << LL_ENDL; + + // Any leftover data at this moment are because protocol was not + // satisfied. Possibly the child was interrupted in the middle of + // sending a message, possibly the child didn't flush stdout before + // terminating, possibly it's just garbage. Log its existence but + // discard it. + LLProcess::ReadPipe& childout(mChild->getReadPipe(LLProcess::STDOUT)); + if (childout.size()) + { + LLProcess::ReadPipe::size_type + peeklen((std::min)(LLProcess::ReadPipe::size_type(50), childout.size())); + LL_WARNS("LLLeap") << "Discarding final " << childout.size() << " bytes: " + << childout.peek(0, peeklen) << "..." << LL_ENDL; + } + + // Kill this instance. MUST BE LAST before return! + delete this; + return false; + } + + // Listener for events on mReplyPump: send to child stdin + bool wstdin(const std::string& pump, const LLSD& data) + { + LLSD packet(LLSDMap("pump", pump)("data", data)); + + std::ostringstream buffer; + buffer << LLSDNotationStreamer(packet); + +/*==========================================================================*| + // DEBUGGING ONLY: don't copy str() if we can avoid it. + std::string strdata(buffer.str()); + if (std::size_t(buffer.tellp()) != strdata.length()) + { + LL_ERRS("LLLeap") << "tellp() -> " << buffer.tellp() << " != " + << "str().length() -> " << strdata.length() << LL_ENDL; + } + // DEBUGGING ONLY: reading back is terribly inefficient. + std::istringstream readback(strdata); + LLSD echo; + LLPointer<LLSDParser> parser(new LLSDNotationParser()); + S32 parse_status(parser->parse(readback, echo, strdata.length())); + if (parse_status == LLSDParser::PARSE_FAILURE) + { + LL_ERRS("LLLeap") << "LLSDNotationParser() cannot parse output of " + << "LLSDNotationStreamer()" << LL_ENDL; + } + if (! llsd_equals(echo, packet)) + { + LL_ERRS("LLLeap") << "LLSDNotationParser() produced different LLSD " + << "than passed to LLSDNotationStreamer()" << LL_ENDL; + } +|*==========================================================================*/ + + LL_DEBUGS("EventHost") << "Sending: " << buffer.tellp() << ':'; + std::string::size_type truncate(80); + if (buffer.tellp() <= truncate) + { + LL_CONT << buffer.str(); + } + else + { + LL_CONT << buffer.str().substr(0, truncate) << "..."; + } + LL_CONT << LL_ENDL; + + LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); + childin.get_ostream() << buffer.tellp() << ':' << buffer.str() << std::flush; + return false; + } + + // Initial state of stateful listening on child stdout: wait for a length + // prefix, followed by ':'. + bool rstdout(const LLSD& data) + { + LLProcess::ReadPipe& childout(mChild->getReadPipe(LLProcess::STDOUT)); + // It's possible we got notified of a couple digit characters without + // seeing the ':' -- unlikely, but still. Until we see ':', keep + // waiting. + if (childout.contains(':')) + { + std::istream& childstream(childout.get_istream()); + // Saw ':', read length prefix and store in mExpect. + size_t expect; + childstream >> expect; + int colon(childstream.get()); + if (colon != ':') + { + // Protocol failure. Clear out the rest of the pending data in + // childout (well, up to a max length) to log what was wrong. + LLProcess::ReadPipe::size_type + readlen((std::min)(childout.size(), LLProcess::ReadPipe::size_type(80))); + bad_protocol(STRINGIZE(expect << char(colon) << childout.read(readlen))); + } + else + { + // Saw length prefix, saw colon, life is good. Now wait for + // that length of data to arrive. + mExpect = expect; + LL_DEBUGS("LLLeap") << "got length, waiting for " + << mExpect << " bytes of data" << LL_ENDL; + // Block calls to this method; resetting mBlocker unblocks + // calls to the other method. + mBlocker.reset(new LLEventPump::Blocker(mStdoutConnection)); + // Go check if we've already received all the advertised data. + if (childout.size()) + { + LLSD updata(data); + updata["len"] = LLSD::Integer(childout.size()); + rstdoutData(updata); + } + } + } + else if (childout.contains('\n')) + { + // Since this is the initial listening state, this is where we'd + // arrive if the child isn't following protocol at all -- say + // because the user specified 'ls' or some darn thing. + bad_protocol(childout.getline()); + } + return false; + } + + // State in which we listen on stdout for the specified length of data to + // arrive. + bool rstdoutData(const LLSD& data) + { + LLProcess::ReadPipe& childout(mChild->getReadPipe(LLProcess::STDOUT)); + // Until we've accumulated the promised length of data, keep waiting. + if (childout.size() >= mExpect) + { + // Ready to rock and roll. + LL_DEBUGS("LLLeap") << "needed " << mExpect << " bytes, got " + << childout.size() << ", parsing LLSD" << LL_ENDL; + LLSD data; + LLPointer<LLSDParser> parser(new LLSDNotationParser()); + S32 parse_status(parser->parse(childout.get_istream(), data, mExpect)); + if (parse_status == LLSDParser::PARSE_FAILURE) + { + bad_protocol("unparseable LLSD data"); + } + else if (! (data.isMap() && data["pump"].isString() && data.has("data"))) + { + // we got an LLSD object, but it lacks required keys + bad_protocol("missing 'pump' or 'data'"); + } + else + { + // The LLSD object we got from our stream contains the keys we + // need. + LLEventPumps::instance().obtain(data["pump"]).post(data["data"]); + // Block calls to this method; resetting mBlocker unblocks calls + // to the other method. + mBlocker.reset(new LLEventPump::Blocker(mStdoutDataConnection)); + // Go check for any more pending events in the buffer. + if (childout.size()) + { + LLSD updata(data); + data["len"] = LLSD::Integer(childout.size()); + rstdout(updata); + } + } + } + return false; + } + + void bad_protocol(const std::string& data) + { + LL_WARNS("LLLeap") << mDesc << ": invalid protocol: " << data << LL_ENDL; + // No point in continuing to run this child. + mChild->kill(); + } + + // Listen on child stderr and log everything that arrives + bool rstderr(const LLSD& data) + { + LLProcess::ReadPipe& childerr(mChild->getReadPipe(LLProcess::STDERR)); + // We might have gotten a notification involving only a partial line + // -- or multiple lines. Read all complete lines; stop when there's + // only a partial line left. + while (childerr.contains('\n')) + { + // DO NOT make calls with side effects in a logging statement! If + // that log level is suppressed, your side effects WON'T HAPPEN. + std::string line(childerr.getline()); + // Log the received line. Prefix it with the desc so we know which + // plugin it's from. This method name rstderr() is intentionally + // chosen to further qualify the log output. + LL_INFOS("LLLeap") << mDesc << ": " << line << LL_ENDL; + } + // What if child writes a final partial line to stderr? + if (data["eof"].asBoolean() && childerr.size()) + { + std::string rest(childerr.read(childerr.size())); + // Read all remaining bytes and log. + LL_INFOS("LLLeap") << mDesc << ": " << rest << LL_ENDL; + } + return false; + } + + void fatalFunction(const std::string& error) + { + // Notify plugin + LLSD event; + event["type"] = "error"; + event["error"] = error; + mReplyPump.post(event); + + // All the above really accomplished was to buffer the serialized + // event in our WritePipe. Have to pump mainloop a couple times to + // really write it out there... but time out in case we can't write. + LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); + LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); + LLSD nop; + F64 until(LLTimer::getElapsedSeconds() + 2); + while (childin.size() && LLTimer::getElapsedSeconds() < until) + { + mainloop.post(nop); + } + + // forward the call to the previous FatalFunction + mPrevFatalFunction(error); + } + +private: + /// We always want to listen on mReplyPump with wstdin(); under some + /// circumstances we'll also echo other LLEventPumps to the plugin. + LLBoundListener connect(LLEventPump& pump, const std::string& listener) + { + // Serialize any event received on the specified LLEventPump to our + // child's stdin, suitably enriched with the pump name on which it was + // received. + return pump.listen(listener, + boost::bind(&LLLeapImpl::wstdin, this, pump.getName(), _1)); + } + + std::string mDesc; + LLEventStream mDonePump; + LLEventStream mReplyPump; + LLProcessPtr mChild; + LLTempBoundListener + mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection; + boost::scoped_ptr<LLEventPump::Blocker> mBlocker; + LLProcess::ReadPipe::size_type mExpect; + LLError::FatalFunction mPrevFatalFunction; + boost::scoped_ptr<LLLeapListener> mListener; +}; + +// This must follow the declaration of LLLeapImpl, so it may as well be last. +LLLeap* LLLeap::create(const std::string& desc, const std::vector<std::string>& plugin, bool exc) +{ + // If caller is willing to permit exceptions, just instantiate. + if (exc) + return new LLLeapImpl(desc, plugin); + + // Caller insists on suppressing LLLeap::Error. Very well, catch it. + try + { + return new LLLeapImpl(desc, plugin); + } + catch (const LLLeap::Error&) + { + return NULL; + } +} + +LLLeap* LLLeap::create(const std::string& desc, const std::string& plugin, bool exc) +{ + // Use LLStringUtil::getTokens() to parse the command line + return create(desc, + LLStringUtil::getTokens(plugin, + " \t\r\n", // drop_delims + "", // no keep_delims + "\"'", // either kind of quotes + "\\"), // backslash escape + exc); +} diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h new file mode 100644 index 0000000000..1a1ad23d39 --- /dev/null +++ b/indra/llcommon/llleap.h @@ -0,0 +1,80 @@ +/** + * @file llleap.h + * @author Nat Goodspeed + * @date 2012-02-20 + * @brief Class that implements "LLSD Event API Plugin" + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLLEAP_H) +#define LL_LLLEAP_H + +#include "llinstancetracker.h" +#include <string> +#include <vector> +#include <stdexcept> + +/** + * LLSD Event API Plugin class. Because instances are managed by + * LLInstanceTracker, you can instantiate LLLeap and forget the instance + * unless you need it later. Each instance manages an LLProcess; when the + * child process terminates, LLLeap deletes itself. We don't require a unique + * LLInstanceTracker key. + * + * The fact that a given LLLeap instance vanishes when its child process + * terminates makes it problematic to store an LLLeap* anywhere. Any stored + * LLLeap* pointer should be validated before use by + * LLLeap::getInstance(LLLeap*) (see LLInstanceTracker). + */ +class LL_COMMON_API LLLeap: public LLInstanceTracker<LLLeap> +{ +public: + /** + * Pass a brief string description, mostly for logging purposes. The desc + * need not be unique, but obviously the clearer we can make it, the + * easier these things will be to debug. The strings are the command line + * used to launch the desired plugin process. + * + * Pass exc=false to suppress LLLeap::Error exception. Obviously in that + * case the caller cannot discover the nature of the error, merely that an + * error of some kind occurred (because create() returned NULL). Either + * way, the error is logged. + */ + static LLLeap* create(const std::string& desc, const std::vector<std::string>& plugin, + bool exc=true); + + /** + * Pass a brief string description, mostly for logging purposes. The desc + * need not be unique, but obviously the clearer we can make it, the + * easier these things will be to debug. Pass a command-line string + * to launch the desired plugin process. + * + * Pass exc=false to suppress LLLeap::Error exception. Obviously in that + * case the caller cannot discover the nature of the error, merely that an + * error of some kind occurred (because create() returned NULL). Either + * way, the error is logged. + */ + static LLLeap* create(const std::string& desc, const std::string& plugin, + bool exc=true); + + /** + * Exception thrown for invalid create() arguments, e.g. no plugin + * program. This is more resiliant than an LL_ERRS failure, because the + * string(s) passed to create() might come from an external source. This + * way the caller can catch LLLeap::Error and try to recover. + */ + struct Error: public std::runtime_error + { + Error(const std::string& what): std::runtime_error(what) {} + }; + + virtual ~LLLeap(); + +protected: + LLLeap(); +}; + +#endif /* ! defined(LL_LLLEAP_H) */ diff --git a/indra/llcommon/llleaplistener.cpp b/indra/llcommon/llleaplistener.cpp new file mode 100644 index 0000000000..fa5730f112 --- /dev/null +++ b/indra/llcommon/llleaplistener.cpp @@ -0,0 +1,287 @@ +/** + * @file llleaplistener.cpp + * @author Nat Goodspeed + * @date 2012-03-16 + * @brief Implementation for llleaplistener. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llleaplistener.h" +// STL headers +// std headers +// external library headers +#include <boost/foreach.hpp> +// other Linden headers +#include "lluuid.h" +#include "llsdutil.h" +#include "stringize.h" + +/***************************************************************************** +* LEAP FEATURE STRINGS +*****************************************************************************/ +/** + * Implement "getFeatures" command. The LLSD map thus obtained is intended to + * be machine-readable (read: easily-parsed, if parsing be necessary) and to + * highlight the differences between this version of the LEAP protocol and + * the baseline version. A client may thus determine whether or not the + * running viewer supports some recent feature of interest. + * + * This method is defined at the top of this implementation file so it's easy + * to find, easy to spot, easy to update as we enhance the LEAP protocol. + */ +/*static*/ LLSD LLLeapListener::getFeatures() +{ + static LLSD features; + if (features.isUndefined()) + { + features = LLSD::emptyMap(); + + // This initial implementation IS the baseline LEAP protocol; thus the + // set of differences is empty; thus features is initially empty. +// features["featurename"] = "value"; + } + + return features; +} + +LLLeapListener::LLLeapListener(const ConnectFunc& connect): + // Each LEAP plugin has an instance of this listener. Make the command + // pump name difficult for other such plugins to guess. + LLEventAPI(LLUUID::generateNewID().asString(), + "Operations relating to the LLSD Event API Plugin (LEAP) protocol"), + mConnect(connect) +{ + LLSD need_name(LLSDMap("name", LLSD())); + add("newpump", + "Instantiate a new LLEventPump named like [\"name\"] and listen to it.\n" + "If [\"type\"] == \"LLEventQueue\", make LLEventQueue, else LLEventStream.\n" + "Events sent through new LLEventPump will be decorated with [\"pump\"]=name.\n" + "Returns actual name in [\"name\"] (may be different if collision).", + &LLLeapListener::newpump, + need_name); + add("killpump", + "Delete LLEventPump [\"name\"] created by \"newpump\".\n" + "Returns [\"status\"] boolean indicating whether such a pump existed.", + &LLLeapListener::killpump, + need_name); + LLSD need_source_listener(LLSDMap("source", LLSD())("listener", LLSD())); + add("listen", + "Listen to an existing LLEventPump named [\"source\"], with listener name\n" + "[\"listener\"].\n" + "By default, send events on [\"source\"] to the plugin, decorated\n" + "with [\"pump\"]=[\"source\"].\n" + "If [\"dest\"] specified, send undecorated events on [\"source\"] to the\n" + "LLEventPump named [\"dest\"].\n" + "Returns [\"status\"] boolean indicating whether the connection was made.", + &LLLeapListener::listen, + need_source_listener); + add("stoplistening", + "Disconnect a connection previously established by \"listen\".\n" + "Pass same [\"source\"] and [\"listener\"] arguments.\n" + "Returns [\"status\"] boolean indicating whether such a listener existed.", + &LLLeapListener::stoplistening, + need_source_listener); + add("ping", + "No arguments, just a round-trip sanity check.", + &LLLeapListener::ping); + add("getAPIs", + "Enumerate all LLEventAPI instances by name and description.", + &LLLeapListener::getAPIs); + add("getAPI", + "Get name, description, dispatch key and operations for LLEventAPI [\"api\"].", + &LLLeapListener::getAPI, + LLSD().with("api", LLSD())); + add("getFeatures", + "Return an LLSD map of feature strings (deltas from baseline LEAP protocol)", + static_cast<void (LLLeapListener::*)(const LLSD&) const>(&LLLeapListener::getFeatures)); + add("getFeature", + "Return the feature value with key [\"feature\"]", + &LLLeapListener::getFeature, + LLSD().with("feature", LLSD())); +} + +LLLeapListener::~LLLeapListener() +{ + // We'd have stored a map of LLTempBoundListener instances, save that the + // operation of inserting into a std::map necessarily copies the + // value_type, and Bad Things would happen if you copied an + // LLTempBoundListener. (Destruction of the original would disconnect the + // listener, invalidating every stored connection.) + BOOST_FOREACH(ListenersMap::value_type& pair, mListeners) + { + pair.second.disconnect(); + } +} + +void LLLeapListener::newpump(const LLSD& request) +{ + Response reply(LLSD(), request); + + std::string name = request["name"]; + LLSD const & type = request["type"]; + + LLEventPump * new_pump = NULL; + if (type.asString() == "LLEventQueue") + { + new_pump = new LLEventQueue(name, true); // tweak name for uniqueness + } + else + { + if (! (type.isUndefined() || type.asString() == "LLEventStream")) + { + reply.warn(STRINGIZE("unknown 'type' " << type << ", using LLEventStream")); + } + new_pump = new LLEventStream(name, true); // tweak name for uniqueness + } + + name = new_pump->getName(); + + mEventPumps.insert(name, new_pump); + + // Now listen on this new pump with our plugin listener + std::string myname("llleap"); + saveListener(name, myname, mConnect(*new_pump, myname)); + + reply["name"] = name; +} + +void LLLeapListener::killpump(const LLSD& request) +{ + Response reply(LLSD(), request); + + std::string name = request["name"]; + // success == (nonzero number of entries were erased) + reply["status"] = bool(mEventPumps.erase(name)); +} + +void LLLeapListener::listen(const LLSD& request) +{ + Response reply(LLSD(), request); + + std::string source_name = request["source"]; + std::string dest_name = request["dest"]; + std::string listener_name = request["listener"]; + + LLEventPump & source = LLEventPumps::instance().obtain(source_name); + + reply["status"] = false; + if (mListeners.find(ListenersMap::key_type(source_name, listener_name)) == mListeners.end()) + { + try + { + if (request["dest"].isDefined()) + { + // If we're asked to connect the "source" pump to a + // specific "dest" pump, find dest pump and connect it. + LLEventPump & dest = LLEventPumps::instance().obtain(dest_name); + saveListener(source_name, listener_name, + source.listen(listener_name, + boost::bind(&LLEventPump::post, &dest, _1))); + } + else + { + // "dest" unspecified means to direct events on "source" + // to our plugin listener. + saveListener(source_name, listener_name, mConnect(source, listener_name)); + } + reply["status"] = true; + } + catch (const LLEventPump::DupListenerName &) + { + // pass - status already set to false + } + } +} + +void LLLeapListener::stoplistening(const LLSD& request) +{ + Response reply(LLSD(), request); + + std::string source_name = request["source"]; + std::string listener_name = request["listener"]; + + ListenersMap::iterator finder = + mListeners.find(ListenersMap::key_type(source_name, listener_name)); + + reply["status"] = false; + if(finder != mListeners.end()) + { + reply["status"] = true; + finder->second.disconnect(); + mListeners.erase(finder); + } +} + +void LLLeapListener::ping(const LLSD& request) const +{ + // do nothing, default reply suffices + Response(LLSD(), request); +} + +void LLLeapListener::getAPIs(const LLSD& request) const +{ + Response reply(LLSD(), request); + + for (LLEventAPI::instance_iter eai(LLEventAPI::beginInstances()), + eaend(LLEventAPI::endInstances()); + eai != eaend; ++eai) + { + LLSD info; + info["desc"] = eai->getDesc(); + reply[eai->getName()] = info; + } +} + +void LLLeapListener::getAPI(const LLSD& request) const +{ + Response reply(LLSD(), request); + + LLEventAPI* found = LLEventAPI::getInstance(request["api"]); + if (found) + { + reply["name"] = found->getName(); + reply["desc"] = found->getDesc(); + reply["key"] = found->getDispatchKey(); + LLSD ops; + for (LLEventAPI::const_iterator oi(found->begin()), oend(found->end()); + oi != oend; ++oi) + { + ops.append(found->getMetadata(oi->first)); + } + reply["ops"] = ops; + } +} + +void LLLeapListener::getFeatures(const LLSD& request) const +{ + // Merely constructing and destroying a Response object suffices here. + // Giving it a name would only produce fatal 'unreferenced variable' + // warnings. + Response(getFeatures(), request); +} + +void LLLeapListener::getFeature(const LLSD& request) const +{ + Response reply(LLSD(), request); + + LLSD::String feature_name(request["feature"]); + LLSD features(getFeatures()); + if (features[feature_name].isDefined()) + { + reply["feature"] = features[feature_name]; + } +} + +void LLLeapListener::saveListener(const std::string& pump_name, + const std::string& listener_name, + const LLBoundListener& listener) +{ + mListeners.insert(ListenersMap::value_type(ListenersMap::key_type(pump_name, listener_name), + listener)); +} diff --git a/indra/llcommon/llleaplistener.h b/indra/llcommon/llleaplistener.h new file mode 100644 index 0000000000..2193d81b9e --- /dev/null +++ b/indra/llcommon/llleaplistener.h @@ -0,0 +1,73 @@ +/** + * @file llleaplistener.h + * @author Nat Goodspeed + * @date 2012-03-16 + * @brief LLEventAPI supporting LEAP plugins + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLLEAPLISTENER_H) +#define LL_LLLEAPLISTENER_H + +#include "lleventapi.h" +#include <map> +#include <string> +#include <boost/function.hpp> +#include <boost/ptr_container/ptr_map.hpp> + +/// Listener class implementing LLLeap query/control operations. +/// See https://jira.lindenlab.com/jira/browse/DEV-31978. +class LLLeapListener: public LLEventAPI +{ +public: + /** + * Decouple LLLeap by dependency injection. Certain LLLeapListener + * operations must be able to cause LLLeap to listen on a specified + * LLEventPump with the LLLeap listener that wraps incoming events in an + * outer (pump=, data=) map and forwards them to the plugin. Very well, + * define the signature for a function that will perform that, and make + * our constructor accept such a function. + */ + typedef boost::function<LLBoundListener(LLEventPump&, const std::string& listener)> + ConnectFunc; + LLLeapListener(const ConnectFunc& connect); + ~LLLeapListener(); + + static LLSD getFeatures(); + +private: + void newpump(const LLSD&); + void killpump(const LLSD&); + void listen(const LLSD&); + void stoplistening(const LLSD&); + void ping(const LLSD&) const; + void getAPIs(const LLSD&) const; + void getAPI(const LLSD&) const; + void getFeatures(const LLSD&) const; + void getFeature(const LLSD&) const; + + void saveListener(const std::string& pump_name, const std::string& listener_name, + const LLBoundListener& listener); + + ConnectFunc mConnect; + + // In theory, listen() could simply call the relevant LLEventPump's + // listen() method, stoplistening() likewise. Lifespan issues make us + // capture the LLBoundListener objects: when this object goes away, all + // those listeners should be disconnected. But what if the client listens, + // stops, listens again on the same LLEventPump with the same listener + // name? Merely collecting LLBoundListeners wouldn't adequately track + // that. So capture the latest LLBoundListener for this LLEventPump name + // and listener name. + typedef std::map<std::pair<std::string, std::string>, LLBoundListener> ListenersMap; + ListenersMap mListeners; + // Similar lifespan reasoning applies to LLEventPumps instantiated by + // newpump() operations. + typedef boost::ptr_map<std::string, LLEventPump> EventPumpsMap; + EventPumpsMap mEventPumps; +}; + +#endif /* ! defined(LL_LLLEAPLISTENER_H) */ diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 75fde8e5ba..1409c55d1c 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -175,7 +175,7 @@ void LLMD5::update(std::istream& stream){ while (stream.good()){ stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable. - len=stream.gcount(); + len=(int)stream.gcount(); update(buffer, len); } diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 31d5f3d2c7..7fdb537ab5 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -132,7 +132,7 @@ #pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual" #pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden #pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored -#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file +//#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file #pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. #pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) #pragma warning( disable : 4996 ) // warning: deprecated @@ -152,6 +152,7 @@ #pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class #pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class #pragma warning (disable : 4018) // '<' : signed/unsigned mismatch + #endif // LL_MSVC #if LL_WINDOWS diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp new file mode 100644 index 0000000000..9667e4e033 --- /dev/null +++ b/indra/llcommon/llprocess.cpp @@ -0,0 +1,1313 @@ +/** + * @file llprocess.cpp + * @brief Utility class for launching, terminating, and tracking the state of processes. + * + * $LicenseInfo:firstyear=2008&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 "llprocess.h" +#include "llsdutil.h" +#include "llsdserialize.h" +#include "llsingleton.h" +#include "llstring.h" +#include "stringize.h" +#include "llapr.h" +#include "apr_signal.h" +#include "llevents.h" + +#include <boost/foreach.hpp> +#include <boost/bind.hpp> +#include <boost/asio/streambuf.hpp> +#include <boost/asio/buffers_iterator.hpp> +#include <iostream> +#include <stdexcept> +#include <limits> +#include <algorithm> +#include <vector> +#include <typeinfo> +#include <utility> + +/***************************************************************************** +* Helpers +*****************************************************************************/ +static const char* whichfile_[] = { "stdin", "stdout", "stderr" }; +static std::string empty; +static LLProcess::Status interpret_status(int status); +static std::string getDesc(const LLProcess::Params& params); + +static std::string whichfile(LLProcess::FILESLOT index) +{ + if (index < LL_ARRAY_SIZE(whichfile_)) + return whichfile_[index]; + return STRINGIZE("file slot " << index); +} + +/** + * Ref-counted "mainloop" listener. As long as there are still outstanding + * LLProcess objects, keep listening on "mainloop" so we can keep polling APR + * for process status. + */ +class LLProcessListener +{ + LOG_CLASS(LLProcessListener); +public: + LLProcessListener(): + mCount(0) + {} + + void addPoll(const LLProcess&) + { + // Unconditionally increment mCount. If it was zero before + // incrementing, listen on "mainloop". + if (mCount++ == 0) + { + LL_DEBUGS("LLProcess") << "listening on \"mainloop\"" << LL_ENDL; + mConnection = LLEventPumps::instance().obtain("mainloop") + .listen("LLProcessListener", boost::bind(&LLProcessListener::tick, this, _1)); + } + } + + void dropPoll(const LLProcess&) + { + // Unconditionally decrement mCount. If it's zero after decrementing, + // stop listening on "mainloop". + if (--mCount == 0) + { + LL_DEBUGS("LLProcess") << "disconnecting from \"mainloop\"" << LL_ENDL; + mConnection.disconnect(); + } + } + +private: + /// called once per frame by the "mainloop" LLEventPump + bool tick(const LLSD&) + { + // Tell APR to sense whether each registered LLProcess is still + // running and call handle_status() appropriately. We should be able + // to get the same info from an apr_proc_wait(APR_NOWAIT) call; but at + // least in APR 1.4.2, testing suggests that even with APR_NOWAIT, + // apr_proc_wait() blocks the caller. We can't have that in the + // viewer. Hence the callback rigmarole. (Once we update APR, it's + // probably worth testing again.) Also -- although there's an + // apr_proc_other_child_refresh() call, i.e. get that information for + // one specific child, it accepts an 'apr_other_child_rec_t*' that's + // mentioned NOWHERE else in the documentation or header files! I + // would use the specific call in LLProcess::getStatus() if I knew + // how. As it is, each call to apr_proc_other_child_refresh_all() will + // call callbacks for ALL still-running child processes. That's why we + // centralize such calls, using "mainloop" to ensure it happens once + // per frame, and refcounting running LLProcess objects to remain + // registered only while needed. + LL_DEBUGS("LLProcess") << "calling apr_proc_other_child_refresh_all()" << LL_ENDL; + apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING); + return false; + } + + /// If this object is destroyed before mCount goes to zero, stop + /// listening on "mainloop" anyway. + LLTempBoundListener mConnection; + unsigned mCount; +}; +static LLProcessListener sProcessListener; + +/***************************************************************************** +* WritePipe and ReadPipe +*****************************************************************************/ +LLProcess::BasePipe::~BasePipe() {} +const LLProcess::BasePipe::size_type + // use funky syntax to call max() to avoid blighted max() macros + LLProcess::BasePipe::npos((std::numeric_limits<LLProcess::BasePipe::size_type>::max)()); + +class WritePipeImpl: public LLProcess::WritePipe +{ + LOG_CLASS(WritePipeImpl); +public: + WritePipeImpl(const std::string& desc, apr_file_t* pipe): + mDesc(desc), + mPipe(pipe), + // Essential to initialize our std::ostream with our special streambuf! + mStream(&mStreambuf) + { + mConnection = LLEventPumps::instance().obtain("mainloop") + .listen(LLEventPump::inventName("WritePipe"), + boost::bind(&WritePipeImpl::tick, this, _1)); + +#if ! LL_WINDOWS + // We can't count on every child process reading everything we try to + // write to it. And if the child terminates with WritePipe data still + // pending, unless we explicitly suppress it, Posix will hit us with + // SIGPIPE. That would terminate the viewer, boom. "Ignoring" it means + // APR gets the correct errno, passes it back to us, we log it, etc. + signal(SIGPIPE, SIG_IGN); +#endif + } + + virtual std::ostream& get_ostream() { return mStream; } + virtual size_type size() const { return mStreambuf.size(); } + + bool tick(const LLSD&) + { + typedef boost::asio::streambuf::const_buffers_type const_buffer_sequence; + // If there's anything to send, try to send it. + std::size_t total(mStreambuf.size()), consumed(0); + if (total) + { + const_buffer_sequence bufs = mStreambuf.data(); + // In general, our streambuf might contain a number of different + // physical buffers; iterate over those. + bool keepwriting = true; + for (const_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end()); + bufi != bufend && keepwriting; ++bufi) + { + // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents + // Although apr_file_write() accepts const void*, we + // manipulate const char* so we can increment the pointer. + const char* remainptr = boost::asio::buffer_cast<const char*>(*bufi); + std::size_t remainlen = boost::asio::buffer_size(*bufi); + while (remainlen) + { + // Tackle the current buffer in discrete chunks. On + // Windows, we've observed strange failures when trying to + // write big lengths (~1 MB) in a single operation. Even a + // 32K chunk seems too large. At some point along the way + // apr_file_write() returns 11 (Resource temporarily + // unavailable, i.e. EAGAIN) and says it wrote 0 bytes -- + // even though it did write the chunk! Our next write + // attempt retries with the same chunk, resulting in the + // chunk being duplicated at the child end. Using smaller + // chunks is empirically more reliable. + std::size_t towrite((std::min)(remainlen, std::size_t(4*1024))); + apr_size_t written(towrite); + apr_status_t err = apr_file_write(mPipe, remainptr, &written); + // EAGAIN is exactly what we want from a nonblocking pipe. + // Rather than waiting for data, it should return immediately. + if (! (err == APR_SUCCESS || APR_STATUS_IS_EAGAIN(err))) + { + LL_WARNS("LLProcess") << "apr_file_write(" << towrite << ") on " << mDesc + << " got " << err << ":" << LL_ENDL; + ll_apr_warn_status(err); + } + + // 'written' is modified to reflect the number of bytes actually + // written. Make sure we consume those later. (Don't consume them + // now, that would invalidate the buffer iterator sequence!) + consumed += written; + // don't forget to advance to next chunk of current buffer + remainptr += written; + remainlen -= written; + + char msgbuf[512]; + LL_DEBUGS("LLProcess") << "wrote " << written << " of " << towrite + << " bytes to " << mDesc + << " (original " << total << ")," + << " code " << err << ": " + << apr_strerror(err, msgbuf, sizeof(msgbuf)) + << LL_ENDL; + + // The parent end of this pipe is nonblocking. If we weren't able + // to write everything we wanted, don't keep banging on it -- that + // won't change until the child reads some. Wait for next tick(). + if (written < towrite) + { + keepwriting = false; // break outer loop over buffers too + break; + } + } // next chunk of current buffer + } // next buffer + // In all, we managed to write 'consumed' bytes. Remove them from the + // streambuf so we don't keep trying to send them. This could be + // anywhere from 0 up to mStreambuf.size(); anything we haven't yet + // sent, we'll try again later. + mStreambuf.consume(consumed); + } + + return false; + } + +private: + std::string mDesc; + apr_file_t* mPipe; + LLTempBoundListener mConnection; + boost::asio::streambuf mStreambuf; + std::ostream mStream; +}; + +class ReadPipeImpl: public LLProcess::ReadPipe +{ + LOG_CLASS(ReadPipeImpl); +public: + ReadPipeImpl(const std::string& desc, apr_file_t* pipe, LLProcess::FILESLOT index): + mDesc(desc), + mPipe(pipe), + mIndex(index), + // Essential to initialize our std::istream with our special streambuf! + mStream(&mStreambuf), + mPump("ReadPipe", true), // tweak name as needed to avoid collisions + mLimit(0), + mEOF(false) + { + mConnection = LLEventPumps::instance().obtain("mainloop") + .listen(LLEventPump::inventName("ReadPipe"), + boost::bind(&ReadPipeImpl::tick, this, _1)); + } + + // Much of the implementation is simply connecting the abstract virtual + // methods with implementation data concealed from the base class. + virtual std::istream& get_istream() { return mStream; } + virtual std::string getline() { return LLProcess::getline(mStream); } + virtual LLEventPump& getPump() { return mPump; } + virtual void setLimit(size_type limit) { mLimit = limit; } + virtual size_type getLimit() const { return mLimit; } + virtual size_type size() const { return mStreambuf.size(); } + + virtual std::string read(size_type len) + { + // Read specified number of bytes into a buffer. + size_type readlen((std::min)(size(), len)); + // Formally, &buffer[0] is invalid for a vector of size() 0. Exit + // early in that situation. + if (! readlen) + return ""; + // Make a buffer big enough. + std::vector<char> buffer(readlen); + mStream.read(&buffer[0], readlen); + // Since we've already clamped 'readlen', we can think of no reason + // why mStream.read() should read fewer than 'readlen' bytes. + // Nonetheless, use the actual retrieved length. + return std::string(&buffer[0], mStream.gcount()); + } + + virtual std::string peek(size_type offset=0, size_type len=npos) const + { + // Constrain caller's offset and len to overlap actual buffer content. + std::size_t real_offset = (std::min)(mStreambuf.size(), std::size_t(offset)); + size_type want_end = (len == npos)? npos : (real_offset + len); + std::size_t real_end = (std::min)(mStreambuf.size(), std::size_t(want_end)); + boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data(); + return std::string(boost::asio::buffers_begin(cbufs) + real_offset, + boost::asio::buffers_begin(cbufs) + real_end); + } + + virtual size_type find(const std::string& seek, size_type offset=0) const + { + // If we're passing a string of length 1, use find(char), which can + // use an O(n) std::find() rather than the O(n^2) std::search(). + if (seek.length() == 1) + { + return find(seek[0], offset); + } + + // If offset is beyond the whole buffer, can't even construct a valid + // iterator range; can't possibly find the string we seek. + if (offset > mStreambuf.size()) + { + return npos; + } + + boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data(); + boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type> + begin(boost::asio::buffers_begin(cbufs)), + end (boost::asio::buffers_end(cbufs)), + found(std::search(begin + offset, end, seek.begin(), seek.end())); + return (found == end)? npos : (found - begin); + } + + virtual size_type find(char seek, size_type offset=0) const + { + // If offset is beyond the whole buffer, can't even construct a valid + // iterator range; can't possibly find the char we seek. + if (offset > mStreambuf.size()) + { + return npos; + } + + boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data(); + boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type> + begin(boost::asio::buffers_begin(cbufs)), + end (boost::asio::buffers_end(cbufs)), + found(std::find(begin + offset, end, seek)); + return (found == end)? npos : (found - begin); + } + + bool tick(const LLSD&) + { + // Once we've hit EOF, skip all the rest of this. + if (mEOF) + return false; + + typedef boost::asio::streambuf::mutable_buffers_type mutable_buffer_sequence; + // Try, every time, to read into our streambuf. In fact, we have no + // idea how much data the child might be trying to send: keep trying + // until we're convinced we've temporarily exhausted the pipe. + enum PipeState { RETRY, EXHAUSTED, CLOSED }; + PipeState state = RETRY; + std::size_t committed(0); + do + { + // attempt to read an arbitrary size + mutable_buffer_sequence bufs = mStreambuf.prepare(4096); + // In general, the mutable_buffer_sequence returned by prepare() might + // contain a number of different physical buffers; iterate over those. + std::size_t tocommit(0); + for (mutable_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end()); + bufi != bufend; ++bufi) + { + // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents + std::size_t toread(boost::asio::buffer_size(*bufi)); + apr_size_t gotten(toread); + apr_status_t err = apr_file_read(mPipe, + boost::asio::buffer_cast<void*>(*bufi), + &gotten); + // EAGAIN is exactly what we want from a nonblocking pipe. + // Rather than waiting for data, it should return immediately. + if (! (err == APR_SUCCESS || APR_STATUS_IS_EAGAIN(err))) + { + // Handle EOF specially: it's part of normal-case processing. + if (err == APR_EOF) + { + LL_DEBUGS("LLProcess") << "EOF on " << mDesc << LL_ENDL; + } + else + { + LL_WARNS("LLProcess") << "apr_file_read(" << toread << ") on " << mDesc + << " got " << err << ":" << LL_ENDL; + ll_apr_warn_status(err); + } + // Either way, though, we won't need any more tick() calls. + mConnection.disconnect(); + // Ignore any subsequent calls we might get anyway. + mEOF = true; + state = CLOSED; // also break outer retry loop + break; + } + + // 'gotten' was modified to reflect the number of bytes actually + // received. Make sure we commit those later. (Don't commit them + // now, that would invalidate the buffer iterator sequence!) + tocommit += gotten; + LL_DEBUGS("LLProcess") << "filled " << gotten << " of " << toread + << " bytes from " << mDesc << LL_ENDL; + + // The parent end of this pipe is nonblocking. If we weren't even + // able to fill this buffer, don't loop to try to fill the next -- + // that won't change until the child writes more. Wait for next + // tick(). + if (gotten < toread) + { + // break outer retry loop too + state = EXHAUSTED; + break; + } + } + + // Don't forget to "commit" the data! + mStreambuf.commit(tocommit); + committed += tocommit; + + // state is changed from RETRY when we can't fill any one buffer + // of the mutable_buffer_sequence established by the current + // prepare() call -- whether due to error or not enough bytes. + // That is, if state is still RETRY, we've filled every physical + // buffer in the mutable_buffer_sequence. In that case, for all we + // know, the child might have still more data pending -- go for it! + } while (state == RETRY); + + // Once we recognize that the pipe is closed, make one more call to + // listener. The listener might be waiting for a particular substring + // to arrive, or a particular length of data or something. The event + // with "eof" == true announces that nothing further will arrive, so + // use it or lose it. + if (committed || state == CLOSED) + { + // If we actually received new data, publish it on our LLEventPump + // as advertised. Constrain it by mLimit. But show listener the + // actual accumulated buffer size, regardless of mLimit. + size_type datasize((std::min)(mLimit, size_type(mStreambuf.size()))); + mPump.post(LLSDMap + ("data", peek(0, datasize)) + ("len", LLSD::Integer(mStreambuf.size())) + ("slot", LLSD::Integer(mIndex)) + ("name", whichfile(mIndex)) + ("desc", mDesc) + ("eof", state == CLOSED)); + } + + return false; + } + +private: + std::string mDesc; + apr_file_t* mPipe; + LLProcess::FILESLOT mIndex; + LLTempBoundListener mConnection; + boost::asio::streambuf mStreambuf; + std::istream mStream; + LLEventStream mPump; + size_type mLimit; + bool mEOF; +}; + +/***************************************************************************** +* LLProcess itself +*****************************************************************************/ +/// Need an exception to avoid constructing an invalid LLProcess object, but +/// internal use only +struct LLProcessError: public std::runtime_error +{ + LLProcessError(const std::string& msg): std::runtime_error(msg) {} +}; + +LLProcessPtr LLProcess::create(const LLSDOrParams& params) +{ + try + { + return LLProcessPtr(new LLProcess(params)); + } + catch (const LLProcessError& e) + { + LL_WARNS("LLProcess") << e.what() << LL_ENDL; + + // If caller is requesting an event on process termination, send one + // indicating bad launch. This may prevent someone waiting forever for + // a termination post that can't arrive because the child never + // started. + if (params.postend.isProvided()) + { + LLEventPumps::instance().obtain(params.postend) + .post(LLSDMap + // no "id" + ("desc", getDesc(params)) + ("state", LLProcess::UNSTARTED) + // no "data" + ("string", e.what()) + ); + } + + return LLProcessPtr(); + } +} + +/// Call an apr function returning apr_status_t. On failure, log warning and +/// throw LLProcessError mentioning the function call that produced that +/// result. +#define chkapr(func) \ + if (ll_apr_warn_status(func)) \ + throw LLProcessError(#func " failed") + +LLProcess::LLProcess(const LLSDOrParams& params): + mAutokill(params.autokill), + mPipes(NSLOTS) +{ + // Hmm, when you construct a ptr_vector with a size, it merely reserves + // space, it doesn't actually make it that big. Explicitly make it bigger. + // Because of ptr_vector's odd semantics, have to push_back(0) the right + // number of times! resize() wants to default-construct new BasePipe + // instances, which fails because it's pure virtual. But because of the + // constructor call, these push_back() calls should require no new + // allocation. + for (size_t i = 0; i < mPipes.capacity(); ++i) + mPipes.push_back(0); + + if (! params.validateBlock(true)) + { + throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n" + << LLSDNotationStreamer(params))); + } + + mPostend = params.postend; + + apr_procattr_t *procattr = NULL; + chkapr(apr_procattr_create(&procattr, gAPRPoolp)); + + // IQA-490, CHOP-900: On Windows, ask APR to jump through hoops to + // constrain the set of handles passed to the child process. Before we + // changed to APR, the Windows implementation of LLProcessLauncher called + // CreateProcess(bInheritHandles=FALSE), meaning to pass NO open handles + // to the child process. Now that we support pipes, though, we must allow + // apr_proc_create() to pass bInheritHandles=TRUE. But without taking + // special pains, that causes trouble in a number of ways, due to the fact + // that the viewer is constantly opening and closing files -- most of + // which CreateProcess() passes to every child process! +#if ! defined(APR_HAS_PROCATTR_CONSTRAIN_HANDLE_SET) + // Our special preprocessor symbol isn't even defined -- wrong APR + LL_WARNS("LLProcess") << "This version of APR lacks Linden " + << "apr_procattr_constrain_handle_set() extension" << LL_ENDL; +#else + chkapr(apr_procattr_constrain_handle_set(procattr, 1)); +#endif + + // For which of stdin, stdout, stderr should we create a pipe to the + // child? In the viewer, there are only a couple viable + // apr_procattr_io_set() alternatives: inherit the viewer's own stdxxx + // handle (APR_NO_PIPE, e.g. for stdout, stderr), or create a pipe that's + // blocking on the child end but nonblocking at the viewer end + // (APR_CHILD_BLOCK). + // Other major options could include explicitly creating a single APR pipe + // and passing it as both stdout and stderr (apr_procattr_child_out_set(), + // apr_procattr_child_err_set()), or accepting a filename, opening it and + // passing that apr_file_t (simple <, >, 2> redirect emulation). + std::vector<apr_int32_t> select; + BOOST_FOREACH(const FileParam& fparam, params.files) + { + // Every iteration, we're going to append an item to 'select'. At the + // top of the loop, its size() is, in effect, an index. Use that to + // pick a string description for messages. + std::string which(whichfile(FILESLOT(select.size()))); + if (fparam.type().empty()) // inherit our file descriptor + { + select.push_back(APR_NO_PIPE); + } + else if (fparam.type() == "pipe") // anonymous pipe + { + if (! fparam.name().empty()) + { + LL_WARNS("LLProcess") << "For " << params.executable() + << ": internal names for reusing pipes ('" + << fparam.name() << "' for " << which + << ") are not yet supported -- creating distinct pipe" + << LL_ENDL; + } + // The viewer can't block for anything: the parent end MUST be + // nonblocking. As the APR documentation itself points out, it + // makes very little sense to set nonblocking I/O for the child + // end of a pipe: only a specially-written child could deal with + // that. + select.push_back(APR_CHILD_BLOCK); + } + else + { + throw LLProcessError(STRINGIZE("For " << params.executable() + << ": unsupported FileParam for " << which + << ": type='" << fparam.type() + << "', name='" << fparam.name() << "'")); + } + } + // By default, pass APR_NO_PIPE for unspecified slots. + while (select.size() < NSLOTS) + { + select.push_back(APR_NO_PIPE); + } + chkapr(apr_procattr_io_set(procattr, select[STDIN], select[STDOUT], select[STDERR])); + + // Thumbs down on implicitly invoking the shell to invoke the child. From + // our point of view, the other major alternative to APR_PROGRAM_PATH + // would be APR_PROGRAM_ENV: still copy environment, but require full + // executable pathname. I don't see a downside to searching the PATH, + // though: if our caller wants (e.g.) a specific Python interpreter, s/he + // can still pass the full pathname. + chkapr(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH)); + // YES, do extra work if necessary to report child exec() failures back to + // parent process. + chkapr(apr_procattr_error_check_set(procattr, 1)); + // Do not start a non-autokill child in detached state. On Posix + // platforms, this setting attempts to daemonize the new child, closing + // std handles and the like, and that's a bit more detachment than we + // want. autokill=false just means not to implicitly kill the child when + // the parent terminates! +// chkapr(apr_procattr_detach_set(procattr, params.autokill? 0 : 1)); + + if (params.autokill) + { +#if ! defined(APR_HAS_PROCATTR_AUTOKILL_SET) + // Our special preprocessor symbol isn't even defined -- wrong APR + LL_WARNS("LLProcess") << "This version of APR lacks Linden apr_procattr_autokill_set() extension" << LL_ENDL; +#elif ! APR_HAS_PROCATTR_AUTOKILL_SET + // Symbol is defined, but to 0: expect apr_procattr_autokill_set() to + // return APR_ENOTIMPL. +#else // APR_HAS_PROCATTR_AUTOKILL_SET nonzero + ll_apr_warn_status(apr_procattr_autokill_set(procattr, 1)); +#endif + } + + // In preparation for calling apr_proc_create(), we collect a number of + // const char* pointers obtained from std::string::c_str(). Turns out + // LLInitParam::Block's helpers Optional, Mandatory, Multiple et al. + // guarantee that converting to the wrapped type (std::string in our + // case), e.g. by calling operator(), returns a reference to *the same + // instance* of the wrapped type that's stored in our Block subclass. + // That's important! We know 'params' persists throughout this method + // call; but without that guarantee, we'd have to assume that converting + // one of its members to std::string might return a different (temp) + // instance. Capturing the c_str() from a temporary std::string is Bad Bad + // Bad. But armed with this knowledge, when you see params.cwd().c_str(), + // grit your teeth and smile and carry on. + + if (params.cwd.isProvided()) + { + chkapr(apr_procattr_dir_set(procattr, params.cwd().c_str())); + } + + // create an argv vector for the child process + std::vector<const char*> argv; + + // Add the executable path. See above remarks about c_str(). + argv.push_back(params.executable().c_str()); + + // Add arguments. See above remarks about c_str(). + BOOST_FOREACH(const std::string& arg, params.args) + { + argv.push_back(arg.c_str()); + } + + // terminate with a null pointer + argv.push_back(NULL); + + // Launch! The NULL would be the environment block, if we were passing + // one. Hand-expand chkapr() macro so we can fill in the actual command + // string instead of the variable names. + if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr, + gAPRPoolp))) + { + throw LLProcessError(STRINGIZE(params << " failed")); + } + + // arrange to call status_callback() + apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in, + gAPRPoolp); + // and make sure we poll it once per "mainloop" tick + sProcessListener.addPoll(*this); + mStatus.mState = RUNNING; + + mDesc = STRINGIZE(getDesc(params) << " (" << mProcess.pid << ')'); + LL_INFOS("LLProcess") << mDesc << ": launched " << params << LL_ENDL; + + // Unless caller explicitly turned off autokill (child should persist), + // take steps to terminate the child. This is all suspenders-and-belt: in + // theory our destructor should kill an autokill child, but in practice + // that doesn't always work (e.g. VWR-21538). + if (params.autokill) + { +/*==========================================================================*| + // NO: There may be an APR bug, not sure -- but at least on Mac, when + // gAPRPoolp is destroyed, OUR process receives SIGTERM! Apparently + // either our own PID is getting into the list of processes to kill() + // (unlikely), or somehow one of those PIDs is getting zeroed first, + // so that kill() sends SIGTERM to the whole process group -- this + // process included. I'd have to build and link with a debug version + // of APR to know for sure. It's too bad: this mechanism would be just + // right for dealing with static autokill LLProcessPtr variables, + // which aren't destroyed until after APR is no longer available. + + // Tie the lifespan of this child process to the lifespan of our APR + // pool: on destruction of the pool, forcibly kill the process. Tell + // APR to try SIGTERM and wait 3 seconds. If that didn't work, use + // SIGKILL. + apr_pool_note_subprocess(gAPRPoolp, &mProcess, APR_KILL_AFTER_TIMEOUT); +|*==========================================================================*/ + + // On Windows, associate the new child process with our Job Object. + autokill(); + } + + // Instantiate the proper pipe I/O machinery + // want to be able to point to apr_proc_t::in, out, err by index + typedef apr_file_t* apr_proc_t::*apr_proc_file_ptr; + static apr_proc_file_ptr members[] = + { &apr_proc_t::in, &apr_proc_t::out, &apr_proc_t::err }; + for (size_t i = 0; i < NSLOTS; ++i) + { + if (select[i] != APR_CHILD_BLOCK) + continue; + std::string desc(STRINGIZE(mDesc << ' ' << whichfile(FILESLOT(i)))); + apr_file_t* pipe(mProcess.*(members[i])); + if (i == STDIN) + { + mPipes.replace(i, new WritePipeImpl(desc, pipe)); + } + else + { + mPipes.replace(i, new ReadPipeImpl(desc, pipe, FILESLOT(i))); + } + LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name() + << "('" << desc << "')" << LL_ENDL; + } +} + +// Helper to obtain a description string, given a Params block +static std::string getDesc(const LLProcess::Params& params) +{ + // If caller specified a description string, by all means use it. + if (params.desc.isProvided()) + return params.desc; + + // Caller didn't say. Use the executable name -- but use just the filename + // part. On Mac, for instance, full pathnames get cumbersome. + return LLProcess::basename(params.executable); +} + +//static +std::string LLProcess::basename(const std::string& path) +{ + // If there are Linden utility functions to manipulate pathnames, I + // haven't found them -- and for this usage, Boost.Filesystem seems kind + // of heavyweight. + std::string::size_type delim = path.find_last_of("\\/"); + // If path contains no pathname delimiters, return the whole thing. + if (delim == std::string::npos) + return path; + + // Return just the part beyond the last delimiter. + return path.substr(delim + 1); +} + +LLProcess::~LLProcess() +{ + // In the Linden viewer, there's at least one static LLProcessPtr. Its + // destructor will be called *after* ll_cleanup_apr(). In such a case, + // unregistering is pointless (and fatal!) -- and kill(), which also + // relies on APR, is impossible. + if (! gAPRPoolp) + return; + + // Only in state RUNNING are we registered for callback. In UNSTARTED we + // haven't yet registered. And since receiving the callback is the only + // way we detect child termination, we only change from state RUNNING at + // the same time we unregister. + if (mStatus.mState == RUNNING) + { + // We're still registered for a callback: unregister. Do it before + // we even issue the kill(): even if kill() somehow prompted an + // instantaneous callback (unlikely), this object is going away! Any + // information updated in this object by such a callback is no longer + // available to any consumer anyway. + apr_proc_other_child_unregister(this); + // One less LLProcess to poll for + sProcessListener.dropPoll(*this); + } + + if (mAutokill) + { + kill("destructor"); + } +} + +bool LLProcess::kill(const std::string& who) +{ + if (isRunning()) + { + LL_INFOS("LLProcess") << who << " killing " << mDesc << LL_ENDL; + +#if LL_WINDOWS + int sig = -1; +#else // Posix + int sig = SIGTERM; +#endif + + ll_apr_warn_status(apr_proc_kill(&mProcess, sig)); + } + + return ! isRunning(); +} + +bool LLProcess::isRunning() const +{ + return getStatus().mState == RUNNING; +} + +LLProcess::Status LLProcess::getStatus() const +{ + return mStatus; +} + +std::string LLProcess::getStatusString() const +{ + return getStatusString(getStatus()); +} + +std::string LLProcess::getStatusString(const Status& status) const +{ + return getStatusString(mDesc, status); +} + +//static +std::string LLProcess::getStatusString(const std::string& desc, const Status& status) +{ + if (status.mState == UNSTARTED) + return desc + " was never launched"; + + if (status.mState == RUNNING) + return desc + " running"; + + if (status.mState == EXITED) + return STRINGIZE(desc << " exited with code " << status.mData); + + if (status.mState == KILLED) +#if LL_WINDOWS + return STRINGIZE(desc << " killed with exception " << std::hex << status.mData); +#else + return STRINGIZE(desc << " killed by signal " << status.mData + << " (" << apr_signal_description_get(status.mData) << ")"); +#endif + + return STRINGIZE(desc << " in unknown state " << status.mState << " (" << status.mData << ")"); +} + +// Classic-C-style APR callback +void LLProcess::status_callback(int reason, void* data, int status) +{ + // Our only role is to bounce this static method call back into object + // space. + static_cast<LLProcess*>(data)->handle_status(reason, status); +} + +#define tabent(symbol) { symbol, #symbol } +static struct ReasonCode +{ + int code; + const char* name; +} reasons[] = +{ + tabent(APR_OC_REASON_DEATH), + tabent(APR_OC_REASON_UNWRITABLE), + tabent(APR_OC_REASON_RESTART), + tabent(APR_OC_REASON_UNREGISTER), + tabent(APR_OC_REASON_LOST), + tabent(APR_OC_REASON_RUNNING) +}; +#undef tabent + +// Object-oriented callback +void LLProcess::handle_status(int reason, int status) +{ + { + // This odd appearance of LL_DEBUGS is just to bracket a lookup that will + // only be performed if in fact we're going to produce the log message. + LL_DEBUGS("LLProcess") << empty; + std::string reason_str; + BOOST_FOREACH(const ReasonCode& rcp, reasons) + { + if (reason == rcp.code) + { + reason_str = rcp.name; + break; + } + } + if (reason_str.empty()) + { + reason_str = STRINGIZE("unknown reason " << reason); + } + LL_CONT << mDesc << ": handle_status(" << reason_str << ", " << status << ")" << LL_ENDL; + } + + if (! (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST)) + { + // We're only interested in the call when the child terminates. + return; + } + + // Somewhat oddly, APR requires that you explicitly unregister even when + // it already knows the child has terminated. We must pass the same 'data' + // pointer as for the register() call, which was our 'this'. + apr_proc_other_child_unregister(this); + // don't keep polling for a terminated process + sProcessListener.dropPoll(*this); + // We overload mStatus.mState to indicate whether the child is registered + // for APR callback: only RUNNING means registered. Track that we've + // unregistered. We know the child has terminated; might be EXITED or + // KILLED; refine below. + mStatus.mState = EXITED; + + // Make last-gasp calls for each of the ReadPipes we have on hand. Since + // they're listening on "mainloop", we can be sure they'll eventually + // collect all pending data from the child. But we want to be able to + // guarantee to our consumer that by the time we post on the "postend" + // LLEventPump, our ReadPipes are already buffering all the data there + // will ever be from the child. That lets the "postend" listener decide + // what to do with that final data. + for (size_t i = 0; i < mPipes.size(); ++i) + { + std::string error; + ReadPipeImpl* ppipe = getPipePtr<ReadPipeImpl>(error, FILESLOT(i)); + if (ppipe) + { + static LLSD trivial; + ppipe->tick(trivial); + } + } + +// wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT); + // It's just wrong to call apr_proc_wait() here. The only way APR knows to + // call us with APR_OC_REASON_DEATH is that it's already reaped this child + // process, so calling wait() will only produce "huh?" from the OS. We + // must rely on the status param passed in, which unfortunately comes + // straight from the OS wait() call, which means we have to decode it by + // hand. + mStatus = interpret_status(status); + LL_INFOS("LLProcess") << getStatusString() << LL_ENDL; + + // If caller requested notification on child termination, send it. + if (! mPostend.empty()) + { + LLEventPumps::instance().obtain(mPostend) + .post(LLSDMap + ("id", getProcessID()) + ("desc", mDesc) + ("state", mStatus.mState) + ("data", mStatus.mData) + ("string", getStatusString()) + ); + } +} + +LLProcess::id LLProcess::getProcessID() const +{ + return mProcess.pid; +} + +LLProcess::handle LLProcess::getProcessHandle() const +{ +#if LL_WINDOWS + return mProcess.hproc; +#else + return mProcess.pid; +#endif +} + +std::string LLProcess::getPipeName(FILESLOT) const +{ + // LLProcess::FileParam::type "npipe" is not yet implemented + return ""; +} + +template<class PIPETYPE> +PIPETYPE* LLProcess::getPipePtr(std::string& error, FILESLOT slot) +{ + if (slot >= NSLOTS) + { + error = STRINGIZE(mDesc << " has no slot " << slot); + return NULL; + } + if (mPipes.is_null(slot)) + { + error = STRINGIZE(mDesc << ' ' << whichfile(slot) << " not a monitored pipe"); + return NULL; + } + // Make sure we dynamic_cast in pointer domain so we can test, rather than + // accepting runtime's exception. + PIPETYPE* ppipe = dynamic_cast<PIPETYPE*>(&mPipes[slot]); + if (! ppipe) + { + error = STRINGIZE(mDesc << ' ' << whichfile(slot) << " not a " << typeid(PIPETYPE).name()); + return NULL; + } + + error.clear(); + return ppipe; +} + +template <class PIPETYPE> +PIPETYPE& LLProcess::getPipe(FILESLOT slot) +{ + std::string error; + PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot); + if (! wp) + { + throw NoPipe(error); + } + return *wp; +} + +template <class PIPETYPE> +boost::optional<PIPETYPE&> LLProcess::getOptPipe(FILESLOT slot) +{ + std::string error; + PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot); + if (! wp) + { + LL_DEBUGS("LLProcess") << error << LL_ENDL; + return boost::optional<PIPETYPE&>(); + } + return *wp; +} + +LLProcess::WritePipe& LLProcess::getWritePipe(FILESLOT slot) +{ + return getPipe<WritePipe>(slot); +} + +boost::optional<LLProcess::WritePipe&> LLProcess::getOptWritePipe(FILESLOT slot) +{ + return getOptPipe<WritePipe>(slot); +} + +LLProcess::ReadPipe& LLProcess::getReadPipe(FILESLOT slot) +{ + return getPipe<ReadPipe>(slot); +} + +boost::optional<LLProcess::ReadPipe&> LLProcess::getOptReadPipe(FILESLOT slot) +{ + return getOptPipe<ReadPipe>(slot); +} + +//static +std::string LLProcess::getline(std::istream& in) +{ + std::string line; + std::getline(in, line); + // Blur the distinction between "\r\n" and plain "\n". std::getline() will + // have eaten the "\n", but we could still end up with a trailing "\r". + std::string::size_type lastpos = line.find_last_not_of("\r"); + if (lastpos != std::string::npos) + { + // Found at least one character that's not a trailing '\r'. SKIP OVER + // IT and erase the rest of the line. + line.erase(lastpos+1); + } + return line; +} + +std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params) +{ + if (params.cwd.isProvided()) + { + out << "cd " << LLStringUtil::quote(params.cwd) << ": "; + } + out << LLStringUtil::quote(params.executable); + BOOST_FOREACH(const std::string& arg, params.args) + { + out << ' ' << LLStringUtil::quote(arg); + } + return out; +} + +/***************************************************************************** +* Windows specific +*****************************************************************************/ +#if LL_WINDOWS + +static std::string WindowsErrorString(const std::string& operation); + +void LLProcess::autokill() +{ + // hopefully now handled by apr_procattr_autokill_set() +} + +LLProcess::handle LLProcess::isRunning(handle h, const std::string& desc) +{ + // This direct Windows implementation is because we have no access to the + // apr_proc_t struct: we expect it's been destroyed. + if (! h) + return 0; + + DWORD waitresult = WaitForSingleObject(h, 0); + if(waitresult == WAIT_OBJECT_0) + { + // the process has completed. + if (! desc.empty()) + { + DWORD status = 0; + if (! GetExitCodeProcess(h, &status)) + { + LL_WARNS("LLProcess") << desc << " terminated, but " + << WindowsErrorString("GetExitCodeProcess()") << LL_ENDL; + } + { + LL_INFOS("LLProcess") << getStatusString(desc, interpret_status(status)) + << LL_ENDL; + } + } + CloseHandle(h); + return 0; + } + + return h; +} + +static LLProcess::Status interpret_status(int status) +{ + LLProcess::Status result; + + // This bit of code is cribbed from apr/threadproc/win32/proc.c, a + // function (unfortunately static) called why_from_exit_code(): + /* See WinNT.h STATUS_ACCESS_VIOLATION and family for how + * this class of failures was determined + */ + if ((status & 0xFFFF0000) == 0xC0000000) + { + result.mState = LLProcess::KILLED; + } + else + { + result.mState = LLProcess::EXITED; + } + result.mData = status; + + return result; +} + +/// GetLastError()/FormatMessage() boilerplate +static std::string WindowsErrorString(const std::string& operation) +{ + int result = GetLastError(); + + LPTSTR error_str = 0; + if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + result, + 0, + (LPTSTR)&error_str, + 0, + NULL) + != 0) + { + // convert from wide-char string to multi-byte string + char message[256]; + wcstombs(message, error_str, sizeof(message)); + message[sizeof(message)-1] = 0; + LocalFree(error_str); + // convert to std::string to trim trailing whitespace + std::string mbsstr(message); + mbsstr.erase(mbsstr.find_last_not_of(" \t\r\n")); + return STRINGIZE(operation << " failed (" << result << "): " << mbsstr); + } + return STRINGIZE(operation << " failed (" << result + << "), but FormatMessage() did not explain"); +} + +/***************************************************************************** +* Posix specific +*****************************************************************************/ +#else // Mac and linux + +#include <signal.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/wait.h> + +void LLProcess::autokill() +{ + // What we ought to do here is to: + // 1. create a unique process group and run all autokill children in that + // group (see https://jira.secondlife.com/browse/SWAT-563); + // 2. figure out a way to intercept control when the viewer exits -- + // gracefully or not; + // 3. when the viewer exits, kill off the aforementioned process group. + + // It's point 2 that's troublesome. Although I've seen some signal- + // handling logic in the Posix viewer code, I haven't yet found any bit of + // code that's run no matter how the viewer exits (a try/finally for the + // whole process, as it were). +} + +// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise. +static bool reap_pid(pid_t pid, LLProcess::Status* pstatus=NULL) +{ + LLProcess::Status dummy; + if (! pstatus) + { + // If caller doesn't want to see Status, give us a target anyway so we + // don't have to have a bunch of conditionals. + pstatus = &dummy; + } + + int status = 0; + pid_t wait_result = ::waitpid(pid, &status, WNOHANG); + if (wait_result == pid) + { + *pstatus = interpret_status(status); + return true; + } + if (wait_result == 0) + { + pstatus->mState = LLProcess::RUNNING; + pstatus->mData = 0; + return false; + } + + // Clear caller's Status block; caller must interpret UNSTARTED to mean + // "if this PID was ever valid, it no longer is." + *pstatus = LLProcess::Status(); + + // We've dealt with the success cases: we were able to reap the child + // (wait_result == pid) or it's still running (wait_result == 0). It may + // be that the child terminated but didn't hang around long enough for us + // to reap. In that case we still have no Status to report, but we can at + // least state that it's not running. + if (wait_result == -1 && errno == ECHILD) + { + // No such process -- this may mean we're ignoring SIGCHILD. + return true; + } + + // Uh, should never happen?! + LL_WARNS("LLProcess") << "LLProcess::reap_pid(): waitpid(" << pid << ") returned " + << wait_result << "; not meaningful?" << LL_ENDL; + // If caller is looping until this pid terminates, and if we can't find + // out, better to break the loop than to claim it's still running. + return true; +} + +LLProcess::id LLProcess::isRunning(id pid, const std::string& desc) +{ + // This direct Posix implementation is because we have no access to the + // apr_proc_t struct: we expect it's been destroyed. + if (! pid) + return 0; + + // Check whether the process has exited, and reap it if it has. + LLProcess::Status status; + if(reap_pid(pid, &status)) + { + // the process has exited. + if (! desc.empty()) + { + std::string statstr(desc + " apparently terminated: no status available"); + // We don't just pass UNSTARTED to getStatusString() because, in + // the context of reap_pid(), that state has special meaning. + if (status.mState != UNSTARTED) + { + statstr = getStatusString(desc, status); + } + LL_INFOS("LLProcess") << statstr << LL_ENDL; + } + return 0; + } + + return pid; +} + +static LLProcess::Status interpret_status(int status) +{ + LLProcess::Status result; + + if (WIFEXITED(status)) + { + result.mState = LLProcess::EXITED; + result.mData = WEXITSTATUS(status); + } + else if (WIFSIGNALED(status)) + { + result.mState = LLProcess::KILLED; + result.mData = WTERMSIG(status); + } + else // uh, shouldn't happen? + { + result.mState = LLProcess::EXITED; + result.mData = status; // someone else will have to decode + } + + return result; +} + +#endif // Posix diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h new file mode 100644 index 0000000000..51010966f9 --- /dev/null +++ b/indra/llcommon/llprocess.h @@ -0,0 +1,546 @@ +/** + * @file llprocess.h + * @brief Utility class for launching, terminating, and tracking child processes. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPROCESS_H +#define LL_LLPROCESS_H + +#include "llinitparam.h" +#include "llsdparam.h" +#include "apr_thread_proc.h" +#include <boost/shared_ptr.hpp> +#include <boost/ptr_container/ptr_vector.hpp> +#include <boost/optional.hpp> +#include <boost/noncopyable.hpp> +#include <iosfwd> // std::ostream +#include <stdexcept> + +#if LL_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include <windows.h> // HANDLE (eye roll) +#elif LL_LINUX +#if defined(Status) +#undef Status +#endif +#endif + +class LLEventPump; + +class LLProcess; +/// LLProcess instances are created on the heap by static factory methods and +/// managed by ref-counted pointers. +typedef boost::shared_ptr<LLProcess> LLProcessPtr; + +/** + * LLProcess handles launching an external process with specified command line + * arguments. It also keeps track of whether the process is still running, and + * can kill it if required. + * + * In discussing LLProcess, we use the term "parent" to refer to this process + * (the process invoking LLProcess), versus "child" to refer to the process + * spawned by LLProcess. + * + * LLProcess relies on periodic post() calls on the "mainloop" LLEventPump: an + * LLProcess object's Status won't update until the next "mainloop" tick. For + * instance, the Second Life viewer's main loop already posts to an + * LLEventPump by that name once per iteration. See + * indra/llcommon/tests/llprocess_test.cpp for an example of waiting for + * child-process termination in a standalone test context. + */ +class LL_COMMON_API LLProcess: public boost::noncopyable +{ + LOG_CLASS(LLProcess); +public: + /** + * Specify what to pass for each of child stdin, stdout, stderr. + * @see LLProcess::Params::files. + */ + struct FileParam: public LLInitParam::Block<FileParam> + { + /** + * type of file handle to pass to child process + * + * - "" (default): let the child inherit the same file handle used by + * this process. For instance, if passed as stdout, child stdout + * will be interleaved with stdout from this process. In this case, + * @a name is moot and should be left "". + * + * - "file": open an OS filesystem file with the specified @a name. + * <i>Not yet implemented.</i> + * + * - "pipe" or "tpipe" or "npipe": depends on @a name + * + * - @a name.empty(): construct an OS pipe used only for this slot + * of the forthcoming child process. + * + * - ! @a name.empty(): in a global registry, find or create (using + * the specified @a name) an OS pipe. The point of the (purely + * internal) @a name is that passing the same @a name in more than + * one slot for a given LLProcess -- or for slots in different + * LLProcess instances -- means the same pipe. For example, you + * might pass the same @a name value as both stdout and stderr to + * make the child process produce both on the same actual pipe. Or + * you might pass the same @a name as the stdout for one LLProcess + * and the stdin for another to connect the two child processes. + * Use LLProcess::getPipeName() to generate a unique name + * guaranteed not to already exist in the registry. <i>Not yet + * implemented.</i> + * + * The difference between "pipe", "tpipe" and "npipe" is as follows. + * + * - "pipe": direct LLProcess to monitor the parent end of the pipe, + * pumping nonblocking I/O every frame. The expectation (at least + * for stdout or stderr) is that the caller will listen for + * incoming data and consume it as it arrives. It's important not + * to neglect such a pipe, because it's buffered in memory. If you + * suspect the child may produce a great volume of output between + * frames, consider directing the child to write to a filesystem + * file instead, then read the file later. + * + * - "tpipe": do not engage LLProcess machinery to monitor the + * parent end of the pipe. A "tpipe" is used only to connect + * different child processes. As such, it makes little sense to + * pass an empty @a name. <i>Not yet implemented.</i> + * + * - "npipe": like "tpipe", but use an OS named pipe with a + * generated name. Note that @a name is the @em internal name of + * the pipe in our global registry -- it doesn't necessarily have + * anything to do with the pipe's name in the OS filesystem. Use + * LLProcess::getPipeName() to obtain the named pipe's OS + * filesystem name, e.g. to pass it as the @a name to another + * LLProcess instance using @a type "file". This supports usage + * like bash's <(subcommand...) or >(subcommand...) + * constructs. <i>Not yet implemented.</i> + * + * In all cases the open mode (read, write) is determined by the child + * slot you're filling. Child stdin means select the "read" end of a + * pipe, or open a filesystem file for reading; child stdout or stderr + * means select the "write" end of a pipe, or open a filesystem file + * for writing. + * + * Confusion such as passing the same pipe as the stdin of two + * processes (rather than stdout for one and stdin for the other) is + * explicitly permitted: it's up to the caller to construct meaningful + * LLProcess pipe graphs. + */ + Optional<std::string> type; + Optional<std::string> name; + + FileParam(const std::string& tp="", const std::string& nm=""): + type("type"), + name("name") + { + // If caller wants to specify values, use explicit assignment to + // set them rather than initialization. + if (! tp.empty()) type = tp; + if (! nm.empty()) name = nm; + } + }; + + /// Param block definition + struct Params: public LLInitParam::Block<Params> + { + Params(): + executable("executable"), + args("args"), + cwd("cwd"), + autokill("autokill", true), + files("files"), + postend("postend"), + desc("desc") + {} + + /// pathname of executable + Mandatory<std::string> executable; + /** + * zero or more additional command-line arguments. Arguments are + * passed through as exactly as we can manage, whitespace and all. + * @note On Windows we manage this by implicitly double-quoting each + * argument while assembling the command line. + */ + Multiple<std::string> args; + /// current working directory, if need it changed + Optional<std::string> cwd; + /// implicitly kill process on destruction of LLProcess object + /// (default true) + Optional<bool> autokill; + /** + * Up to three FileParam items: for child stdin, stdout, stderr. + * Passing two FileParam entries means default treatment for stderr, + * and so forth. + * + * @note LLInitParam::Block permits usage like this: + * @code + * LLProcess::Params params; + * ... + * params.files + * .add(LLProcess::FileParam()) // stdin + * .add(LLProcess::FileParam().type("pipe") // stdout + * .add(LLProcess::FileParam().type("file").name("error.log")); + * @endcode + * + * @note While it's theoretically plausible to pass additional open + * file handles to a child specifically written to expect them, our + * underlying implementation doesn't yet support that. + */ + Multiple<FileParam, AtMost<3> > files; + /** + * On child-process termination, if this LLProcess object still + * exists, post LLSD event to LLEventPump with specified name (default + * no event). Event contains at least: + * + * - "id" as obtained from getProcessID() + * - "desc" short string description of child (executable + pid) + * - "state" @c state enum value, from Status.mState + * - "data" if "state" is EXITED, exit code; if KILLED, on Posix, + * signal number + * - "string" English text describing "state" and "data" (e.g. "exited + * with code 0") + */ + Optional<std::string> postend; + /** + * Description of child process for logging purposes. It need not be + * unique; the logged description string will contain the PID as well. + * If this is omitted, a description will be derived from the + * executable name. + */ + Optional<std::string> desc; + }; + typedef LLSDParamAdapter<Params> LLSDOrParams; + + /** + * Factory accepting either plain LLSD::Map or Params block. + * MAY RETURN DEFAULT-CONSTRUCTED LLProcessPtr if params invalid! + */ + static LLProcessPtr create(const LLSDOrParams& params); + virtual ~LLProcess(); + + /// Is child process still running? + bool isRunning() const; + + /** + * State of child process + */ + enum state + { + UNSTARTED, ///< initial value, invisible to consumer + RUNNING, ///< child process launched + EXITED, ///< child process terminated voluntarily + KILLED ///< child process terminated involuntarily + }; + + /** + * Status info + */ + struct Status + { + Status(): + mState(UNSTARTED), + mData(0) + {} + + state mState; ///< @see state + /** + * - for mState == EXITED: mData is exit() code + * - for mState == KILLED: mData is signal number (Posix) + * - otherwise: mData is undefined + */ + int mData; + }; + + /// Status query + Status getStatus() const; + /// English Status string query, for logging etc. + std::string getStatusString() const; + /// English Status string query for previously-captured Status + std::string getStatusString(const Status& status) const; + /// static English Status string query + static std::string getStatusString(const std::string& desc, const Status& status); + + // Attempt to kill the process -- returns true if the process is no longer running when it returns. + // Note that even if this returns false, the process may exit some time after it's called. + bool kill(const std::string& who=""); + +#if LL_WINDOWS + typedef int id; ///< as returned by getProcessID() + typedef HANDLE handle; ///< as returned by getProcessHandle() +#else + typedef pid_t id; + typedef pid_t handle; +#endif + /** + * Get an int-like id value. This is primarily intended for a human reader + * to differentiate processes. + */ + id getProcessID() const; + /** + * Get a "handle" of a kind that you might pass to platform-specific API + * functions to engage features not directly supported by LLProcess. + */ + handle getProcessHandle() const; + + /** + * Test if a process (@c handle obtained from getProcessHandle()) is still + * running. Return same nonzero @c handle value if still running, else + * zero, so you can test it like a bool. But if you want to update a + * stored variable as a side effect, you can write code like this: + * @code + * hchild = LLProcess::isRunning(hchild); + * @endcode + * @note This method is intended as a unit-test hook, not as the first of + * a whole set of operations supported on freestanding @c handle values. + * New functionality should be added as nonstatic members operating on + * the same data as getProcessHandle(). + * + * In particular, if child termination is detected by static isRunning() + * rather than by nonstatic isRunning(), the LLProcess object won't be + * aware of the child's changed status and may encounter OS errors trying + * to obtain it. static isRunning() is only intended for after the + * launching LLProcess object has been destroyed. + */ + static handle isRunning(handle, const std::string& desc=""); + + /// Provide symbolic access to child's file slots + enum FILESLOT { STDIN=0, STDOUT=1, STDERR=2, NSLOTS=3 }; + + /** + * For a pipe constructed with @a type "npipe", obtain the generated OS + * filesystem name for the specified pipe. Otherwise returns the empty + * string. @see LLProcess::FileParam::type + */ + std::string getPipeName(FILESLOT) const; + + /// base of ReadPipe, WritePipe + class LL_COMMON_API BasePipe + { + public: + virtual ~BasePipe() = 0; + + typedef std::size_t size_type; + static const size_type npos; + + /** + * Get accumulated buffer length. + * + * For WritePipe, is there still pending data to send to child? + * + * For ReadPipe, we often need to refrain from actually reading the + * std::istream returned by get_istream() until we've accumulated + * enough data to make it worthwhile. For instance, if we're expecting + * a number from the child, but the child happens to flush "12" before + * emitting "3\n", get_istream() >> myint could return 12 rather than + * 123! + */ + virtual size_type size() const = 0; + }; + + /// As returned by getWritePipe() or getOptWritePipe() + class WritePipe: public BasePipe + { + public: + /** + * Get ostream& on which to write to child's stdin. + * + * @usage + * @code + * myProcess->getWritePipe().get_ostream() << "Hello, child!" << std::endl; + * @endcode + */ + virtual std::ostream& get_ostream() = 0; + }; + + /// As returned by getReadPipe() or getOptReadPipe() + class ReadPipe: public BasePipe + { + public: + /** + * Get istream& on which to read from child's stdout or stderr. + * + * @usage + * @code + * std::string stuff; + * myProcess->getReadPipe().get_istream() >> stuff; + * @endcode + * + * You should be sure in advance that the ReadPipe in question can + * fill the request. @see getPump() + */ + virtual std::istream& get_istream() = 0; + + /** + * Like std::getline(get_istream(), line), but trims off trailing '\r' + * to make calling code less platform-sensitive. + */ + virtual std::string getline() = 0; + + /** + * Like get_istream().read(buffer, n), but returns std::string rather + * than requiring caller to construct a buffer, etc. + */ + virtual std::string read(size_type len) = 0; + + /** + * Peek at accumulated buffer data without consuming it. Optional + * parameters give you substr() functionality. + * + * @note You can discard buffer data using get_istream().ignore(n). + */ + virtual std::string peek(size_type offset=0, size_type len=npos) const = 0; + + /** + * Detect presence of a substring (or char) in accumulated buffer data + * without retrieving it. Optional offset allows you to search from + * specified position. + */ + template <typename SEEK> + bool contains(SEEK seek, size_type offset=0) const + { return find(seek, offset) != npos; } + + /** + * Search for a substring in accumulated buffer data without + * retrieving it. Returns size_type position at which found, or npos + * meaning not found. Optional offset allows you to search from + * specified position. + */ + virtual size_type find(const std::string& seek, size_type offset=0) const = 0; + + /** + * Search for a char in accumulated buffer data without retrieving it. + * Returns size_type position at which found, or npos meaning not + * found. Optional offset allows you to search from specified + * position. + */ + virtual size_type find(char seek, size_type offset=0) const = 0; + + /** + * Get LLEventPump& on which to listen for incoming data. The posted + * LLSD::Map event will contain: + * + * - "data" part of pending data; see setLimit() + * - "len" entire length of pending data, regardless of setLimit() + * - "slot" this ReadPipe's FILESLOT, e.g. LLProcess::STDOUT + * - "name" e.g. "stdout" + * - "desc" e.g. "SLPlugin (pid) stdout" + * - "eof" @c true means there no more data will arrive on this pipe, + * therefore no more events on this pump + * + * If the child sends "abc", and this ReadPipe posts "data"="abc", but + * you don't consume it by reading the std::istream returned by + * get_istream(), and the child next sends "def", ReadPipe will post + * "data"="abcdef". + */ + virtual LLEventPump& getPump() = 0; + + /** + * Set maximum length of buffer data that will be posted in the LLSD + * announcing arrival of new data from the child. If you call + * setLimit(5), and the child sends "abcdef", the LLSD event will + * contain "data"="abcde". However, you may still read the entire + * "abcdef" from get_istream(): this limit affects only the size of + * the data posted with the LLSD event. If you don't call this method, + * @em no data will be posted: the default is 0 bytes. + */ + virtual void setLimit(size_type limit) = 0; + + /** + * Query the current setLimit() limit. + */ + virtual size_type getLimit() const = 0; + }; + + /// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to + /// create a pipe at the corresponding FILESLOT. + struct NoPipe: public std::runtime_error + { + NoPipe(const std::string& what): std::runtime_error(what) {} + }; + + /** + * Get a reference to the (only) WritePipe for this LLProcess. @a slot, if + * specified, must be STDIN. Throws NoPipe if you did not request a "pipe" + * for child stdin. Use this method when you know how you created the + * LLProcess in hand. + */ + WritePipe& getWritePipe(FILESLOT slot=STDIN); + + /** + * Get a boost::optional<WritePipe&> to the (only) WritePipe for this + * LLProcess. @a slot, if specified, must be STDIN. The return value is + * empty if you did not request a "pipe" for child stdin. Use this method + * for inspecting an LLProcess you did not create. + */ + boost::optional<WritePipe&> getOptWritePipe(FILESLOT slot=STDIN); + + /** + * Get a reference to one of the ReadPipes for this LLProcess. @a slot, if + * specified, must be STDOUT or STDERR. Throws NoPipe if you did not + * request a "pipe" for child stdout or stderr. Use this method when you + * know how you created the LLProcess in hand. + */ + ReadPipe& getReadPipe(FILESLOT slot); + + /** + * Get a boost::optional<ReadPipe&> to one of the ReadPipes for this + * LLProcess. @a slot, if specified, must be STDOUT or STDERR. The return + * value is empty if you did not request a "pipe" for child stdout or + * stderr. Use this method for inspecting an LLProcess you did not create. + */ + boost::optional<ReadPipe&> getOptReadPipe(FILESLOT slot); + + /// little utilities that really should already be somewhere else in the + /// code base + static std::string basename(const std::string& path); + static std::string getline(std::istream&); + +private: + /// constructor is private: use create() instead + LLProcess(const LLSDOrParams& params); + void autokill(); + // Classic-C-style APR callback + static void status_callback(int reason, void* data, int status); + // Object-oriented callback + void handle_status(int reason, int status); + // implementation for get[Opt][Read|Write]Pipe() + template <class PIPETYPE> + PIPETYPE& getPipe(FILESLOT slot); + template <class PIPETYPE> + boost::optional<PIPETYPE&> getOptPipe(FILESLOT slot); + template <class PIPETYPE> + PIPETYPE* getPipePtr(std::string& error, FILESLOT slot); + + std::string mDesc; + std::string mPostend; + apr_proc_t mProcess; + bool mAutokill; + Status mStatus; + // explicitly want this ptr_vector to be able to store NULLs + typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector; + PipeVector mPipes; +}; + +/// for logging +LL_COMMON_API std::ostream& operator<<(std::ostream&, const LLProcess::Params&); + +#endif // LL_LLPROCESS_H diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp deleted file mode 100644 index 10950181fd..0000000000 --- a/indra/llcommon/llprocesslauncher.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/** - * @file llprocesslauncher.cpp - * @brief Utility class for launching, terminating, and tracking the state of processes. - * - * $LicenseInfo:firstyear=2008&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 "llprocesslauncher.h" - -#include <iostream> -#if LL_DARWIN || LL_LINUX -// not required or present on Win32 -#include <sys/wait.h> -#endif - -LLProcessLauncher::LLProcessLauncher() -{ -#if LL_WINDOWS - mProcessHandle = 0; -#else - mProcessID = 0; -#endif -} - -LLProcessLauncher::~LLProcessLauncher() -{ - kill(); -} - -void LLProcessLauncher::setExecutable(const std::string &executable) -{ - mExecutable = executable; -} - -void LLProcessLauncher::setWorkingDirectory(const std::string &dir) -{ - mWorkingDir = dir; -} - -const std::string& LLProcessLauncher::getExecutable() const -{ - return mExecutable; -} - -void LLProcessLauncher::clearArguments() -{ - mLaunchArguments.clear(); -} - -void LLProcessLauncher::addArgument(const std::string &arg) -{ - mLaunchArguments.push_back(arg); -} - -void LLProcessLauncher::addArgument(const char *arg) -{ - mLaunchArguments.push_back(std::string(arg)); -} - -#if LL_WINDOWS - -int LLProcessLauncher::launch(void) -{ - // If there was already a process associated with this object, kill it. - kill(); - orphan(); - - int result = 0; - - PROCESS_INFORMATION pinfo; - STARTUPINFOA sinfo; - memset(&sinfo, 0, sizeof(sinfo)); - - std::string args = mExecutable; - for(int i = 0; i < (int)mLaunchArguments.size(); i++) - { - args += " "; - args += mLaunchArguments[i]; - } - - // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... - char *args2 = new char[args.size() + 1]; - strcpy(args2, args.c_str()); - - const char * working_directory = 0; - if(!mWorkingDir.empty()) working_directory = mWorkingDir.c_str(); - if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, working_directory, &sinfo, &pinfo ) ) - { - result = GetLastError(); - - LPTSTR error_str = 0; - if( - FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - result, - 0, - (LPTSTR)&error_str, - 0, - NULL) - != 0) - { - char message[256]; - wcstombs(message, error_str, 256); - message[255] = 0; - llwarns << "CreateProcessA failed: " << message << llendl; - LocalFree(error_str); - } - - if(result == 0) - { - // Make absolutely certain we return a non-zero value on failure. - result = -1; - } - } - else - { - // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on - // CloseHandle(pinfo.hProcess); // stops leaks - nothing else - mProcessHandle = pinfo.hProcess; - CloseHandle(pinfo.hThread); // stops leaks - nothing else - } - - delete[] args2; - - return result; -} - -bool LLProcessLauncher::isRunning(void) -{ - if(mProcessHandle != 0) - { - DWORD waitresult = WaitForSingleObject(mProcessHandle, 0); - if(waitresult == WAIT_OBJECT_0) - { - // the process has completed. - mProcessHandle = 0; - } - } - - return (mProcessHandle != 0); -} -bool LLProcessLauncher::kill(void) -{ - bool result = true; - - if(mProcessHandle != 0) - { - TerminateProcess(mProcessHandle,0); - - if(isRunning()) - { - result = false; - } - } - - return result; -} - -void LLProcessLauncher::orphan(void) -{ - // Forget about the process - mProcessHandle = 0; -} - -// static -void LLProcessLauncher::reap(void) -{ - // No actions necessary on Windows. -} - -#else // Mac and linux - -#include <signal.h> -#include <fcntl.h> -#include <errno.h> - -static std::list<pid_t> sZombies; - -// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise. -static bool reap_pid(pid_t pid) -{ - bool result = false; - - pid_t wait_result = ::waitpid(pid, NULL, WNOHANG); - if(wait_result == pid) - { - result = true; - } - else if(wait_result == -1) - { - if(errno == ECHILD) - { - // No such process -- this may mean we're ignoring SIGCHILD. - result = true; - } - } - - return result; -} - -int LLProcessLauncher::launch(void) -{ - // If there was already a process associated with this object, kill it. - kill(); - orphan(); - - int result = 0; - int current_wd = -1; - - // create an argv vector for the child process - const char ** fake_argv = new const char *[mLaunchArguments.size() + 2]; // 1 for the executable path, 1 for the NULL terminator - - int i = 0; - - // add the executable path - fake_argv[i++] = mExecutable.c_str(); - - // and any arguments - for(int j=0; j < mLaunchArguments.size(); j++) - fake_argv[i++] = mLaunchArguments[j].c_str(); - - // terminate with a null pointer - fake_argv[i] = NULL; - - if(!mWorkingDir.empty()) - { - // save the current working directory - current_wd = ::open(".", O_RDONLY); - - // and change to the one the child will be executed in - if (::chdir(mWorkingDir.c_str())) - { - // chdir failed - } - } - - // flush all buffers before the child inherits them - ::fflush(NULL); - - pid_t id = vfork(); - if(id == 0) - { - // child process - - ::execv(mExecutable.c_str(), (char * const *)fake_argv); - - // If we reach this point, the exec failed. - // Use _exit() instead of exit() per the vfork man page. - _exit(0); - } - - // parent process - - if(current_wd >= 0) - { - // restore the previous working directory - if (::fchdir(current_wd)) - { - // chdir failed - } - ::close(current_wd); - } - - delete[] fake_argv; - - mProcessID = id; - - return result; -} - -bool LLProcessLauncher::isRunning(void) -{ - if(mProcessID != 0) - { - // Check whether the process has exited, and reap it if it has. - if(reap_pid(mProcessID)) - { - // the process has exited. - mProcessID = 0; - } - } - - return (mProcessID != 0); -} - -bool LLProcessLauncher::kill(void) -{ - bool result = true; - - if(mProcessID != 0) - { - // Try to kill the process. We'll do approximately the same thing whether the kill returns an error or not, so we ignore the result. - (void)::kill(mProcessID, SIGTERM); - - // This will have the side-effect of reaping the zombie if the process has exited. - if(isRunning()) - { - result = false; - } - } - - return result; -} - -void LLProcessLauncher::orphan(void) -{ - // Disassociate the process from this object - if(mProcessID != 0) - { - // We may still need to reap the process's zombie eventually - sZombies.push_back(mProcessID); - - mProcessID = 0; - } -} - -// static -void LLProcessLauncher::reap(void) -{ - // Attempt to real all saved process ID's. - - std::list<pid_t>::iterator iter = sZombies.begin(); - while(iter != sZombies.end()) - { - if(reap_pid(*iter)) - { - iter = sZombies.erase(iter); - } - else - { - iter++; - } - } -} - -#endif diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h deleted file mode 100644 index 954c249147..0000000000 --- a/indra/llcommon/llprocesslauncher.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file llprocesslauncher.h - * @brief Utility class for launching, terminating, and tracking the state of processes. - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPROCESSLAUNCHER_H -#define LL_LLPROCESSLAUNCHER_H - -#if LL_WINDOWS -#include <windows.h> -#endif - - -/* - LLProcessLauncher handles launching external processes with specified command line arguments. - It also keeps track of whether the process is still running, and can kill it if required. -*/ - -class LL_COMMON_API LLProcessLauncher -{ - LOG_CLASS(LLProcessLauncher); -public: - LLProcessLauncher(); - virtual ~LLProcessLauncher(); - - void setExecutable(const std::string &executable); - void setWorkingDirectory(const std::string &dir); - - const std::string& getExecutable() const; - - void clearArguments(); - void addArgument(const std::string &arg); - void addArgument(const char *arg); - - int launch(void); - bool isRunning(void); - - // Attempt to kill the process -- returns true if the process is no longer running when it returns. - // Note that even if this returns false, the process may exit some time after it's called. - bool kill(void); - - // Use this if you want the external process to continue execution after the LLProcessLauncher instance controlling it is deleted. - // Normally, the destructor will attempt to kill the process and wait for termination. - // This should only be used if the viewer is about to exit -- otherwise, the child process will become a zombie after it exits. - void orphan(void); - - // This needs to be called periodically on Mac/Linux to clean up zombie processes. - static void reap(void); - - // Accessors for platform-specific process ID -#if LL_WINDOWS - HANDLE getProcessHandle() { return mProcessHandle; }; -#else - pid_t getProcessID() { return mProcessID; }; -#endif - -private: - std::string mExecutable; - std::string mWorkingDir; - std::vector<std::string> mLaunchArguments; - -#if LL_WINDOWS - HANDLE mProcessHandle; -#else - pid_t mProcessID; -#endif -}; - -#endif // LL_LLPROCESSLAUNCHER_H diff --git a/indra/llxuixml/llregistry.h b/indra/llcommon/llregistry.h index 36ce6a97b7..36d7f7a44c 100644 --- a/indra/llxuixml/llregistry.h +++ b/indra/llcommon/llregistry.h @@ -31,6 +31,7 @@ #include <boost/type_traits.hpp> #include "llsingleton.h" +#include "lltypeinfolookup.h" template <typename T> class LLRegistryDefaultComparator @@ -38,6 +39,24 @@ class LLRegistryDefaultComparator bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; } }; +template <typename KEY, typename VALUE> +struct LLRegistryMapSelector +{ + typedef std::map<KEY, VALUE> type; +}; + +template <typename VALUE> +struct LLRegistryMapSelector<std::type_info*, VALUE> +{ + typedef LLTypeInfoLookup<VALUE> type; +}; + +template <typename VALUE> +struct LLRegistryMapSelector<const std::type_info*, VALUE> +{ + typedef LLTypeInfoLookup<VALUE> type; +}; + template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> > class LLRegistry { @@ -53,7 +72,7 @@ public: { friend class LLRegistry<KEY, VALUE, COMPARATOR>; public: - typedef typename std::map<KEY, VALUE> registry_map_t; + typedef typename LLRegistryMapSelector<KEY, VALUE>::type registry_map_t; bool add(ref_const_key_t key, ref_const_value_t value) { diff --git a/indra/llui/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 0e29873bb0..0e29873bb0 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp diff --git a/indra/llui/llsdparam.h b/indra/llcommon/llsdparam.h index 3dfc6d020e..6ef5debd7b 100644 --- a/indra/llui/llsdparam.h +++ b/indra/llcommon/llsdparam.h @@ -31,7 +31,7 @@ #include "llinitparam.h" #include "boost/function.hpp" -struct LLParamSDParserUtilities +struct LL_COMMON_API LLParamSDParserUtilities { static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range); @@ -40,7 +40,7 @@ struct LLParamSDParserUtilities static void readSDValues(read_sd_cb_t cb, const LLSD& sd); }; -class LLParamSDParser +class LL_COMMON_API LLParamSDParser : public LLInitParam::Parser { LOG_CLASS(LLParamSDParser); @@ -92,7 +92,7 @@ private: }; -extern LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR; +extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR; template<typename T> class LLSDParamAdapter : public T { diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index bf62600514..b419101b7e 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -110,7 +110,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ { legacy_no_header = true; - inbuf = str.gcount(); + inbuf = (int)str.gcount(); } else { @@ -343,7 +343,7 @@ std::istream& LLSDParser::get( char delim) const { istr.get(s, n, delim); - if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); return istr; } @@ -353,7 +353,7 @@ std::istream& LLSDParser::get( char delim) const { istr.get(sb, delim); - if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); return istr; } @@ -377,7 +377,7 @@ std::istream& LLSDParser::read( std::streamsize n) const { istr.read(s, n); - if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); return istr; } @@ -789,7 +789,7 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const if(len) { value.resize(len); - account(fullread(istr, (char *)&value[0], len)); + account((int)fullread(istr, (char *)&value[0], len)); } c = get(istr); // strip off the trailing double-quote data = value; @@ -1069,7 +1069,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const if(size > 0) { value.resize(size); - account(fullread(istr, (char*)&value[0], size)); + account((int)fullread(istr, (char*)&value[0], size)); } data = value; } @@ -1200,7 +1200,7 @@ bool LLSDBinaryParser::parseString( if(size) { buf.resize(size); - account(fullread(istr, &buf[0], size)); + account((int)fullread(istr, &buf[0], size)); value.assign(buf.begin(), buf.end()); } return true; @@ -1642,7 +1642,7 @@ int deserialize_string_raw( const S32 BUF_LEN = 20; char buf[BUF_LEN]; /* Flawfinder: ignore */ istr.get(buf, BUF_LEN - 1, ')'); - count += istr.gcount(); + count += (int)istr.gcount(); int c = istr.get(); c = istr.get(); count += 2; @@ -1657,7 +1657,7 @@ int deserialize_string_raw( if(len) { buf.resize(len); - count += fullread(istr, (char *)&buf[0], len); + count += (int)fullread(istr, (char *)&buf[0], len); value.assign(buf.begin(), buf.end()); } c = istr.get(); diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index be9db53906..34b3dbb99a 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -464,7 +464,7 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data) } } - status = XML_ParseBuffer(mParser, num_read, false); + status = XML_ParseBuffer(mParser, (int)num_read, false); if (status == XML_STATUS_ERROR) { break; diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 65c7297cbf..532d3f9341 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -308,7 +308,7 @@ class LLSDParam<T> \ { \ public: \ LLSDParam(const LLSD& value): \ - _value(value.AS()) \ + _value((T)value.AS()) \ {} \ \ operator T() const { return _value; } \ diff --git a/indra/llcommon/llsortedvector.h b/indra/llcommon/llsortedvector.h new file mode 100644 index 0000000000..391b82ee44 --- /dev/null +++ b/indra/llcommon/llsortedvector.h @@ -0,0 +1,152 @@ +/** + * @file llsortedvector.h + * @author Nat Goodspeed + * @date 2012-04-08 + * @brief LLSortedVector class wraps a vector that we maintain in sorted + * order so we can perform binary-search lookups. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLSORTEDVECTOR_H) +#define LL_LLSORTEDVECTOR_H + +#include <vector> +#include <algorithm> + +/** + * LLSortedVector contains a std::vector<std::pair> that we keep sorted on the + * first of the pair. This makes insertion somewhat more expensive than simple + * std::vector::push_back(), but allows us to use binary search for lookups. + * It's intended for small aggregates where lookup is far more performance- + * critical than insertion; in such cases a binary search on a small, sorted + * std::vector can be more performant than a std::map lookup. + */ +template <typename KEY, typename VALUE> +class LLSortedVector +{ +public: + typedef LLSortedVector<KEY, VALUE> self; + typedef KEY key_type; + typedef VALUE mapped_type; + typedef std::pair<key_type, mapped_type> value_type; + typedef std::vector<value_type> PairVector; + typedef typename PairVector::iterator iterator; + typedef typename PairVector::const_iterator const_iterator; + + /// Empty + LLSortedVector() {} + + /// Fixed initial size + LLSortedVector(std::size_t size): + mVector(size) + {} + + /// Bulk load + template <typename ITER> + LLSortedVector(ITER begin, ITER end): + mVector(begin, end) + { + // Allow caller to dump in a bunch of (pairs convertible to) + // value_type if desired, but make sure we sort afterwards. + std::sort(mVector.begin(), mVector.end()); + } + + /// insert(key, value) + std::pair<iterator, bool> insert(const key_type& key, const mapped_type& value) + { + return insert(value_type(key, value)); + } + + /// insert(value_type) + std::pair<iterator, bool> insert(const value_type& pair) + { + typedef std::pair<iterator, bool> iterbool; + iterator found = std::lower_bound(mVector.begin(), mVector.end(), pair, + less<value_type>()); + // have to check for end() before it's even valid to dereference + if (found == mVector.end()) + { + std::size_t index(mVector.size()); + mVector.push_back(pair); + // don't forget that push_back() invalidates 'found' + return iterbool(mVector.begin() + index, true); + } + if (found->first == pair.first) + { + return iterbool(found, false); + } + // remember that insert() invalidates 'found' -- save index + std::size_t index(found - mVector.begin()); + mVector.insert(found, pair); + // okay, convert from index back to iterator + return iterbool(mVector.begin() + index, true); + } + + iterator begin() { return mVector.begin(); } + iterator end() { return mVector.end(); } + const_iterator begin() const { return mVector.begin(); } + const_iterator end() const { return mVector.end(); } + + bool empty() const { return mVector.empty(); } + std::size_t size() const { return mVector.size(); } + + /// find + iterator find(const key_type& key) + { + iterator found = std::lower_bound(mVector.begin(), mVector.end(), + value_type(key, mapped_type()), + less<value_type>()); + if (found == mVector.end() || found->first != key) + return mVector.end(); + return found; + } + + const_iterator find(const key_type& key) const + { + return const_cast<self*>(this)->find(key); + } + +private: + // Define our own 'less' comparator so we can specialize without messing + // with std::less. + template <typename T> + struct less: public std::less<T> {}; + + // Specialize 'less' for an LLSortedVector::value_type involving + // std::type_info*. This is one of LLSortedVector's foremost use cases. We + // specialize 'less' rather than just defining a specific comparator + // because LLSortedVector should be usable for other key_types as well. + template <typename T> + struct less< std::pair<std::type_info*, T> >: + public std::binary_function<std::pair<std::type_info*, T>, + std::pair<std::type_info*, T>, + bool> + { + bool operator()(const std::pair<std::type_info*, T>& lhs, + const std::pair<std::type_info*, T>& rhs) const + { + return lhs.first->before(*rhs.first); + } + }; + + // Same as above, but with const std::type_info*. + template <typename T> + struct less< std::pair<const std::type_info*, T> >: + public std::binary_function<std::pair<const std::type_info*, T>, + std::pair<const std::type_info*, T>, + bool> + { + bool operator()(const std::pair<const std::type_info*, T>& lhs, + const std::pair<const std::type_info*, T>& rhs) const + { + return lhs.first->before(*rhs.first); + } + }; + + PairVector mVector; +}; + +#endif /* ! defined(LL_LLSORTEDVECTOR_H) */ diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index b2c495d093..057257057f 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -593,7 +593,7 @@ void LLStatTime::stop() { if ( LLStatAccum::SCALE_PER_FRAME == scale ) { - return mTotalTimeInFrame; + return (F32)mTotalTimeInFrame; } else { diff --git a/indra/llcommon/llstreamqueue.cpp b/indra/llcommon/llstreamqueue.cpp new file mode 100644 index 0000000000..1116a2b6a2 --- /dev/null +++ b/indra/llcommon/llstreamqueue.cpp @@ -0,0 +1,24 @@ +/** + * @file llstreamqueue.cpp + * @author Nat Goodspeed + * @date 2012-01-05 + * @brief Implementation for llstreamqueue. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llstreamqueue.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +// As of this writing, llstreamqueue.h is entirely template-based, therefore +// we don't strictly need a corresponding .cpp file. However, our CMake test +// macro assumes one. Here it is. +bool llstreamqueue_cpp_ignored = true; diff --git a/indra/llcommon/llstreamqueue.h b/indra/llcommon/llstreamqueue.h new file mode 100644 index 0000000000..0726bad175 --- /dev/null +++ b/indra/llcommon/llstreamqueue.h @@ -0,0 +1,240 @@ +/** + * @file llstreamqueue.h + * @author Nat Goodspeed + * @date 2012-01-04 + * @brief Definition of LLStreamQueue + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLSTREAMQUEUE_H) +#define LL_LLSTREAMQUEUE_H + +#include <string> +#include <list> +#include <iosfwd> // std::streamsize +#include <boost/iostreams/categories.hpp> + +/** + * This class is a growable buffer between a producer and consumer. It serves + * as a queue usable with Boost.Iostreams -- hence, a "stream queue." + * + * This is especially useful for buffering nonblocking I/O. For instance, we + * want application logic to be able to serialize LLSD to a std::ostream. We + * may write more data than the destination pipe can handle all at once, but + * it's imperative NOT to block the application-level serialization call. So + * we buffer it instead. Successive frames can try nonblocking writes to the + * destination pipe until all buffered data has been sent. + * + * Similarly, we want application logic be able to deserialize LLSD from a + * std::istream. Again, we must not block that deserialize call waiting for + * more data to arrive from the input pipe! Instead we build up a buffer over + * a number of frames, using successive nonblocking reads, until we have + * "enough" data to be able to present it through a std::istream. + * + * @note The use cases for this class overlap somewhat with those for the + * LLIOPipe/LLPumpIO hierarchies, and indeed we considered using those. This + * class has two virtues over the older machinery: + * + * # It's vastly simpler -- way fewer concepts. It's not clear to me whether + * there were ever LLIOPipe/etc. use cases that demanded all the fanciness + * rolled in, or whether they were simply overdesigned. In any case, no + * remaining Lindens will admit to familiarity with those classes -- and + * they're sufficiently obtuse that it would take considerable learning + * curve to figure out how to use them properly. The bottom line is that + * current management is not keen on any more engineers climbing that curve. + * # This class is designed around available components such as std::string, + * std::list, Boost.Iostreams. There's less proprietary code. + */ +template <typename Ch> +class LLGenericStreamQueue +{ +public: + LLGenericStreamQueue(): + mSize(0), + mClosed(false) + {} + + /** + * Boost.Iostreams Source Device facade for use with other Boost.Iostreams + * functionality. LLGenericStreamQueue doesn't quite fit any of the Boost + * 1.48 Iostreams concepts; instead it behaves as both a Sink and a + * Source. This is its Source facade. + */ + struct Source + { + typedef Ch char_type; + typedef boost::iostreams::source_tag category; + + /// Bind the underlying LLGenericStreamQueue + Source(LLGenericStreamQueue& sq): + mStreamQueue(sq) + {} + + // Read up to n characters from the underlying data source into the + // buffer s, returning the number of characters read; return -1 to + // indicate EOF + std::streamsize read(Ch* s, std::streamsize n) + { + return mStreamQueue.read(s, n); + } + + LLGenericStreamQueue& mStreamQueue; + }; + + /** + * Boost.Iostreams Sink Device facade for use with other Boost.Iostreams + * functionality. LLGenericStreamQueue doesn't quite fit any of the Boost + * 1.48 Iostreams concepts; instead it behaves as both a Sink and a + * Source. This is its Sink facade. + */ + struct Sink + { + typedef Ch char_type; + typedef boost::iostreams::sink_tag category; + + /// Bind the underlying LLGenericStreamQueue + Sink(LLGenericStreamQueue& sq): + mStreamQueue(sq) + {} + + /// Write up to n characters from the buffer s to the output sequence, + /// returning the number of characters written + std::streamsize write(const Ch* s, std::streamsize n) + { + return mStreamQueue.write(s, n); + } + + /// Send EOF to consumer + void close() + { + mStreamQueue.close(); + } + + LLGenericStreamQueue& mStreamQueue; + }; + + /// Present Boost.Iostreams Source facade + Source asSource() { return Source(*this); } + /// Present Boost.Iostreams Sink facade + Sink asSink() { return Sink(*this); } + + /// append data to buffer + std::streamsize write(const Ch* s, std::streamsize n) + { + // Unclear how often we might be asked to write 0 bytes -- perhaps a + // naive caller responding to an unready nonblocking read. But if we + // do get such a call, don't add a completely empty BufferList entry. + if (n == 0) + return n; + // We could implement this using a single std::string object, a la + // ostringstream. But the trouble with appending to a string is that + // you might have to recopy all previous contents to grow its size. If + // we want this to scale to large data volumes, better to allocate + // individual pieces. + mBuffer.push_back(string(s, n)); + mSize += n; + return n; + } + + /** + * Inform this LLGenericStreamQueue that no further data are forthcoming. + * For our purposes, close() is strictly a producer-side operation; + * there's little point in closing the consumer side. + */ + void close() + { + mClosed = true; + } + + /// consume data from buffer + std::streamsize read(Ch* s, std::streamsize n) + { + // read() is actually a convenience method for peek() followed by + // skip(). + std::streamsize got(peek(s, n)); + // We can only skip() as many characters as we can peek(); ignore + // skip() return here. + skip(n); + return got; + } + + /// Retrieve data from buffer without consuming. Like read(), return -1 on + /// EOF. + std::streamsize peek(Ch* s, std::streamsize n) const; + + /// Consume data from buffer without retrieving. Unlike read() and peek(), + /// at EOF we simply skip 0 characters. + std::streamsize skip(std::streamsize n); + + /// How many characters do we currently have buffered? + std::streamsize size() const + { + return mSize; + } + +private: + typedef std::basic_string<Ch> string; + typedef std::list<string> BufferList; + BufferList mBuffer; + std::streamsize mSize; + bool mClosed; +}; + +template <typename Ch> +std::streamsize LLGenericStreamQueue<Ch>::peek(Ch* s, std::streamsize n) const +{ + // Here we may have to build up 'n' characters from an arbitrary + // number of individual BufferList entries. + typename BufferList::const_iterator bli(mBuffer.begin()), blend(mBuffer.end()); + // Indicate EOF if producer has closed the pipe AND we've exhausted + // all previously-buffered data. + if (mClosed && bli == blend) + { + return -1; + } + // Here either producer hasn't yet closed, or we haven't yet exhausted + // remaining data. + std::streamsize needed(n), got(0); + // Loop until either we run out of BufferList entries or we've + // completely satisfied the request. + for ( ; bli != blend && needed; ++bli) + { + std::streamsize chunk(std::min(needed, std::streamsize(bli->length()))); + std::copy(bli->begin(), bli->begin() + chunk, s); + needed -= chunk; + s += chunk; + got += chunk; + } + return got; +} + +template <typename Ch> +std::streamsize LLGenericStreamQueue<Ch>::skip(std::streamsize n) +{ + typename BufferList::iterator bli(mBuffer.begin()), blend(mBuffer.end()); + std::streamsize toskip(n), skipped(0); + while (bli != blend && toskip >= bli->length()) + { + std::streamsize chunk(bli->length()); + typename BufferList::iterator zap(bli++); + mBuffer.erase(zap); + mSize -= chunk; + toskip -= chunk; + skipped += chunk; + } + if (bli != blend && toskip) + { + bli->erase(bli->begin(), bli->begin() + toskip); + mSize -= toskip; + skipped += toskip; + } + return skipped; +} + +typedef LLGenericStreamQueue<char> LLStreamQueue; +typedef LLGenericStreamQueue<wchar_t> LLWStreamQueue; + +#endif /* ! defined(LL_LLSTREAMQUEUE_H) */ diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index e7fe656808..fa0eb9f72c 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -912,22 +912,24 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions); template<> void LLStringUtil::getTokens(const std::string& instr, std::vector<std::string >& tokens, const std::string& delims) { - std::string currToken; - std::string::size_type begIdx, endIdx; - - begIdx = instr.find_first_not_of (delims); - while (begIdx != std::string::npos) + // Starting at offset 0, scan forward for the next non-delimiter. We're + // done when the only characters left in 'instr' are delimiters. + for (std::string::size_type begIdx, endIdx = 0; + (begIdx = instr.find_first_not_of (delims, endIdx)) != std::string::npos; ) { + // Found a non-delimiter. After that, find the next delimiter. endIdx = instr.find_first_of (delims, begIdx); if (endIdx == std::string::npos) { + // No more delimiters: this token extends to the end of the string. endIdx = instr.length(); } - currToken = instr.substr(begIdx, endIdx - begIdx); + // extract the token between begIdx and endIdx; substr() needs length + std::string currToken(instr.substr(begIdx, endIdx - begIdx)); LLStringUtil::trim (currToken); tokens.push_back(currToken); - begIdx = instr.find_first_not_of (delims, endIdx); + // next scan past delimiters starts at endIdx } } diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 7e41e787b5..09733e8e2a 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -40,6 +40,7 @@ #endif #include <string.h> +#include <boost/scoped_ptr.hpp> #if LL_SOLARIS // stricmp and strnicmp do not exist on Solaris: @@ -237,40 +238,77 @@ private: static std::string sLocale; public: - typedef typename std::basic_string<T>::size_type size_type; + typedef std::basic_string<T> string_type; + typedef typename string_type::size_type size_type; public: ///////////////////////////////////////////////////////////////////////////////////////// // Static Utility functions that operate on std::strings - static const std::basic_string<T> null; + static const string_type null; typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; - LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims); - LL_COMMON_API static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals); - LL_COMMON_API static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch); - LL_COMMON_API static S32 format(std::basic_string<T>& s, const format_map_t& substitutions); - LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions); - LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions); - LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions); + /// considers any sequence of delims as a single field separator + LL_COMMON_API static void getTokens(const string_type& instr, + std::vector<string_type >& tokens, + const string_type& delims); + /// like simple scan overload, but returns scanned vector + static std::vector<string_type> getTokens(const string_type& instr, + const string_type& delims); + /// add support for keep_delims and quotes (either could be empty string) + static void getTokens(const string_type& instr, + std::vector<string_type>& tokens, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes=string_type()); + /// like keep_delims-and-quotes overload, but returns scanned vector + static std::vector<string_type> getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes=string_type()); + /// add support for escapes (could be empty string) + static void getTokens(const string_type& instr, + std::vector<string_type>& tokens, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes, + const string_type& escapes); + /// like escapes overload, but returns scanned vector + static std::vector<string_type> getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes, + const string_type& escapes); + + LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals); + LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch); + LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions); + LL_COMMON_API static S32 format(string_type& s, const LLSD& substitutions); + LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const format_map_t& substitutions); + LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const LLSD& substitutions); LL_COMMON_API static void setLocale (std::string inLocale); LL_COMMON_API static std::string getLocale (void); - static bool isValidIndex(const std::basic_string<T>& string, size_type i) + static bool isValidIndex(const string_type& string, size_type i) { return !string.empty() && (0 <= i) && (i <= string.size()); } - static void trimHead(std::basic_string<T>& string); - static void trimTail(std::basic_string<T>& string); - static void trim(std::basic_string<T>& string) { trimHead(string); trimTail(string); } - static void truncate(std::basic_string<T>& string, size_type count); + static bool contains(const string_type& string, T c, size_type i=0) + { + return string.find(c, i) != string_type::npos; + } - static void toUpper(std::basic_string<T>& string); - static void toLower(std::basic_string<T>& string); + static void trimHead(string_type& string); + static void trimTail(string_type& string); + static void trim(string_type& string) { trimHead(string); trimTail(string); } + static void truncate(string_type& string, size_type count); + + static void toUpper(string_type& string); + static void toLower(string_type& string); // True if this is the head of s. - static BOOL isHead( const std::basic_string<T>& string, const T* s ); + static BOOL isHead( const string_type& string, const T* s ); /** * @brief Returns true if string starts with substr @@ -278,8 +316,8 @@ public: * If etither string or substr are empty, this method returns false. */ static bool startsWith( - const std::basic_string<T>& string, - const std::basic_string<T>& substr); + const string_type& string, + const string_type& substr); /** * @brief Returns true if string ends in substr @@ -287,19 +325,32 @@ public: * If etither string or substr are empty, this method returns false. */ static bool endsWith( - const std::basic_string<T>& string, - const std::basic_string<T>& substr); + const string_type& string, + const string_type& substr); - static void addCRLF(std::basic_string<T>& string); - static void removeCRLF(std::basic_string<T>& string); + static void addCRLF(string_type& string); + static void removeCRLF(string_type& string); - static void replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab ); - static void replaceNonstandardASCII( std::basic_string<T>& string, T replacement ); - static void replaceChar( std::basic_string<T>& string, T target, T replacement ); - static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement ); + static void replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab ); + static void replaceNonstandardASCII( string_type& string, T replacement ); + static void replaceChar( string_type& string, T target, T replacement ); + static void replaceString( string_type& string, string_type target, string_type replacement ); - static BOOL containsNonprintable(const std::basic_string<T>& string); - static void stripNonprintable(std::basic_string<T>& string); + static BOOL containsNonprintable(const string_type& string); + static void stripNonprintable(string_type& string); + + /** + * Double-quote an argument string if needed, unless it's already + * double-quoted. Decide whether it's needed based on the presence of any + * character in @a triggers (default space or double-quote). If we quote + * it, escape any embedded double-quote with the @a escape string (default + * backslash). + * + * Passing triggers="" means always quote, unless it's already double-quoted. + */ + static string_type quote(const string_type& str, + const string_type& triggers=" \"", + const string_type& escape="\\"); /** * @brief Unsafe way to make ascii characters. You should probably @@ -308,18 +359,18 @@ public: * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII * should work. */ - static void _makeASCII(std::basic_string<T>& string); + static void _makeASCII(string_type& string); // Conversion to other data types - static BOOL convertToBOOL(const std::basic_string<T>& string, BOOL& value); - static BOOL convertToU8(const std::basic_string<T>& string, U8& value); - static BOOL convertToS8(const std::basic_string<T>& string, S8& value); - static BOOL convertToS16(const std::basic_string<T>& string, S16& value); - static BOOL convertToU16(const std::basic_string<T>& string, U16& value); - static BOOL convertToU32(const std::basic_string<T>& string, U32& value); - static BOOL convertToS32(const std::basic_string<T>& string, S32& value); - static BOOL convertToF32(const std::basic_string<T>& string, F32& value); - static BOOL convertToF64(const std::basic_string<T>& string, F64& value); + static BOOL convertToBOOL(const string_type& string, BOOL& value); + static BOOL convertToU8(const string_type& string, U8& value); + static BOOL convertToS8(const string_type& string, S8& value); + static BOOL convertToS16(const string_type& string, S16& value); + static BOOL convertToU16(const string_type& string, U16& value); + static BOOL convertToU32(const string_type& string, U32& value); + static BOOL convertToS32(const string_type& string, S32& value); + static BOOL convertToF32(const string_type& string, F32& value); + static BOOL convertToF64(const string_type& string, F64& value); ///////////////////////////////////////////////////////////////////////////////////////// // Utility functions for working with char*'s and strings @@ -327,24 +378,24 @@ public: // Like strcmp but also handles empty strings. Uses // current locale. static S32 compareStrings(const T* lhs, const T* rhs); - static S32 compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs); + static S32 compareStrings(const string_type& lhs, const string_type& rhs); // case insensitive version of above. Uses current locale on // Win32, and falls back to a non-locale aware comparison on // Linux. static S32 compareInsensitive(const T* lhs, const T* rhs); - static S32 compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs); + static S32 compareInsensitive(const string_type& lhs, const string_type& rhs); // Case sensitive comparison with good handling of numbers. Does not use current locale. // a.k.a. strdictcmp() - static S32 compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b); + static S32 compareDict(const string_type& a, const string_type& b); // Case *in*sensitive comparison with good handling of numbers. Does not use current locale. // a.k.a. strdictcmp() - static S32 compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b); + static S32 compareDictInsensitive(const string_type& a, const string_type& b); // Puts compareDict() in a form appropriate for LL container classes to use for sorting. - static BOOL precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b ); + static BOOL precedesDict( const string_type& a, const string_type& b ); // A replacement for strncpy. // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds @@ -352,7 +403,7 @@ public: static void copy(T* dst, const T* src, size_type dst_size); // Copies src into dst at a given offset. - static void copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset); + static void copyInto(string_type& dst, const string_type& src, size_type offset); static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); } @@ -362,7 +413,7 @@ public: #endif private: - LL_COMMON_API static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens); + LL_COMMON_API static size_type getSubstitution(const string_type& instr, size_type& start, std::vector<string_type >& tokens); }; template<class T> const std::basic_string<T> LLStringUtilBase<T>::null; @@ -636,10 +687,325 @@ namespace LLStringFn //////////////////////////////////////////////////////////// // NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp. // There is no LLWStringUtil::format implementation currently. -// Calling thse for anything other than LLStringUtil will produce link errors. +// Calling these for anything other than LLStringUtil will produce link errors. //////////////////////////////////////////////////////////// +// static +template <class T> +std::vector<typename LLStringUtilBase<T>::string_type> +LLStringUtilBase<T>::getTokens(const string_type& instr, const string_type& delims) +{ + std::vector<string_type> tokens; + getTokens(instr, tokens, delims); + return tokens; +} + +// static +template <class T> +std::vector<typename LLStringUtilBase<T>::string_type> +LLStringUtilBase<T>::getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes) +{ + std::vector<string_type> tokens; + getTokens(instr, tokens, drop_delims, keep_delims, quotes); + return tokens; +} + +// static +template <class T> +std::vector<typename LLStringUtilBase<T>::string_type> +LLStringUtilBase<T>::getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes, + const string_type& escapes) +{ + std::vector<string_type> tokens; + getTokens(instr, tokens, drop_delims, keep_delims, quotes, escapes); + return tokens; +} + +namespace LLStringUtilBaseImpl +{ + +/** + * Input string scanner helper for getTokens(), or really any other + * character-parsing routine that may have to deal with escape characters. + * This implementation defines the concept (also an interface, should you + * choose to implement the concept by subclassing) and provides trivial + * implementations for a string @em without escape processing. + */ +template <class T> +struct InString +{ + typedef std::basic_string<T> string_type; + typedef typename string_type::const_iterator const_iterator; + + InString(const_iterator b, const_iterator e): + mIter(b), + mEnd(e) + {} + virtual ~InString() {} + + bool done() const { return mIter == mEnd; } + /// Is the current character (*mIter) escaped? This implementation can + /// answer trivially because it doesn't support escapes. + virtual bool escaped() const { return false; } + /// Obtain the current character and advance @c mIter. + virtual T next() { return *mIter++; } + /// Does the current character match specified character? + virtual bool is(T ch) const { return (! done()) && *mIter == ch; } + /// Is the current character any one of the specified characters? + virtual bool oneof(const string_type& delims) const + { + return (! done()) && LLStringUtilBase<T>::contains(delims, *mIter); + } + + /** + * Scan forward from @from until either @a delim or end. This is primarily + * useful for processing quoted substrings. + * + * If we do see @a delim, append everything from @from until (excluding) + * @a delim to @a into, advance @c mIter to skip @a delim, and return @c + * true. + * + * If we do not see @a delim, do not alter @a into or @c mIter and return + * @c false. Do not pass GO, do not collect $200. + * + * @note The @c false case described above implements normal getTokens() + * treatment of an unmatched open quote: treat the quote character as if + * escaped, that is, simply collect it as part of the current token. Other + * plausible behaviors directly affect the way getTokens() deals with an + * unmatched quote: e.g. throwing an exception to treat it as an error, or + * assuming a close quote beyond end of string (in which case return @c + * true). + */ + virtual bool collect_until(string_type& into, const_iterator from, T delim) + { + const_iterator found = std::find(from, mEnd, delim); + // If we didn't find delim, change nothing, just tell caller. + if (found == mEnd) + return false; + // Found delim! Append everything between from and found. + into.append(from, found); + // advance past delim in input + mIter = found + 1; + return true; + } + + const_iterator mIter, mEnd; +}; + +/// InString subclass that handles escape characters +template <class T> +class InEscString: public InString<T> +{ +public: + typedef InString<T> super; + typedef typename super::string_type string_type; + typedef typename super::const_iterator const_iterator; + using super::done; + using super::mIter; + using super::mEnd; + + InEscString(const_iterator b, const_iterator e, const string_type& escapes): + super(b, e), + mEscapes(escapes) + { + // Even though we've already initialized 'mIter' via our base-class + // constructor, set it again to check for initial escape char. + setiter(b); + } + + /// This implementation uses the answer cached by setiter(). + virtual bool escaped() const { return mIsEsc; } + virtual T next() + { + // If we're looking at the escape character of an escape sequence, + // skip that character. This is the one time we can modify 'mIter' + // without using setiter: for this one case we DO NOT CARE if the + // escaped character is itself an escape. + if (mIsEsc) + ++mIter; + // If we were looking at an escape character, this is the escaped + // character; otherwise it's just the next character. + T result(*mIter); + // Advance mIter, checking for escape sequence. + setiter(mIter + 1); + return result; + } + + virtual bool is(T ch) const + { + // Like base-class is(), except that an escaped character matches + // nothing. + return (! done()) && (! mIsEsc) && *mIter == ch; + } + + virtual bool oneof(const string_type& delims) const + { + // Like base-class oneof(), except that an escaped character matches + // nothing. + return (! done()) && (! mIsEsc) && LLStringUtilBase<T>::contains(delims, *mIter); + } + + virtual bool collect_until(string_type& into, const_iterator from, T delim) + { + // Deal with escapes in the characters we collect; that is, an escaped + // character must become just that character without the preceding + // escape. Collect characters in a separate string rather than + // directly appending to 'into' in case we do not find delim, in which + // case we're supposed to leave 'into' unmodified. + string_type collected; + // For scanning purposes, we're going to work directly with 'mIter'. + // Save its current value in case we fail to see delim. + const_iterator save_iter(mIter); + // Okay, set 'mIter', checking for escape. + setiter(from); + while (! done()) + { + // If we see an unescaped delim, stop and report success. + if ((! mIsEsc) && *mIter == delim) + { + // Append collected chars to 'into'. + into.append(collected); + // Don't forget to advance 'mIter' past delim. + setiter(mIter + 1); + return true; + } + // We're not at end, and either we're not looking at delim or it's + // escaped. Collect this character and keep going. + collected.push_back(next()); + } + // Here we hit 'mEnd' without ever seeing delim. Restore mIter and tell + // caller. + setiter(save_iter); + return false; + } + +private: + void setiter(const_iterator i) + { + mIter = i; + + // Every time we change 'mIter', set 'mIsEsc' to be able to repetitively + // answer escaped() without having to rescan 'mEscapes'. mIsEsc caches + // contains(mEscapes, *mIter). + + // We're looking at an escaped char if we're not already at end (that + // is, *mIter is even meaningful); if *mIter is in fact one of the + // specified escape characters; and if there's one more character + // following it. That is, if an escape character is the very last + // character of the input string, it loses its special meaning. + mIsEsc = (! done()) && + LLStringUtilBase<T>::contains(mEscapes, *mIter) && + (mIter+1) != mEnd; + } + + const string_type mEscapes; + bool mIsEsc; +}; + +/// getTokens() implementation based on InString concept +template <typename INSTRING, typename string_type> +void getTokens(INSTRING& instr, std::vector<string_type>& tokens, + const string_type& drop_delims, const string_type& keep_delims, + const string_type& quotes) +{ + // There are times when we want to match either drop_delims or + // keep_delims. Concatenate them up front to speed things up. + string_type all_delims(drop_delims + keep_delims); + // no tokens yet + tokens.clear(); + + // try for another token + while (! instr.done()) + { + // scan past any drop_delims + while (instr.oneof(drop_delims)) + { + // skip this drop_delim + instr.next(); + // but if that was the end of the string, done + if (instr.done()) + return; + } + // found the start of another token: make a slot for it + tokens.push_back(string_type()); + if (instr.oneof(keep_delims)) + { + // *iter is a keep_delim, a token of exactly 1 character. Append + // that character to the new token and proceed. + tokens.back().push_back(instr.next()); + continue; + } + // Here we have a non-delimiter token, which might consist of a mix of + // quoted and unquoted parts. Use bash rules for quoting: you can + // embed a quoted substring in the midst of an unquoted token (e.g. + // ~/"sub dir"/myfile.txt); you can ram two quoted substrings together + // to make a single token (e.g. 'He said, "'"Don't."'"'). We diverge + // from bash in that bash considers an unmatched quote an error. Our + // param signature doesn't allow for errors, so just pretend it's not + // a quote and embed it. + // At this level, keep scanning until we hit the next delimiter of + // either type (drop_delims or keep_delims). + while (! instr.oneof(all_delims)) + { + // If we're looking at an open quote, search forward for + // a close quote, collecting characters along the way. + if (instr.oneof(quotes) && + instr.collect_until(tokens.back(), instr.mIter+1, *instr.mIter)) + { + // collect_until is cleverly designed to do exactly what we + // need here. No further action needed if it returns true. + } + else + { + // Either *iter isn't a quote, or there's no matching close + // quote: in other words, just an ordinary char. Append it to + // current token. + tokens.back().push_back(instr.next()); + } + // having scanned that segment of this token, if we've reached the + // end of the string, we're done + if (instr.done()) + return; + } + } +} + +} // namespace LLStringUtilBaseImpl + +// static +template <class T> +void LLStringUtilBase<T>::getTokens(const string_type& string, std::vector<string_type>& tokens, + const string_type& drop_delims, const string_type& keep_delims, + const string_type& quotes) +{ + // Because this overload doesn't support escapes, use simple InString to + // manage input range. + LLStringUtilBaseImpl::InString<T> instring(string.begin(), string.end()); + LLStringUtilBaseImpl::getTokens(instring, tokens, drop_delims, keep_delims, quotes); +} + +// static +template <class T> +void LLStringUtilBase<T>::getTokens(const string_type& string, std::vector<string_type>& tokens, + const string_type& drop_delims, const string_type& keep_delims, + const string_type& quotes, const string_type& escapes) +{ + // This overload must deal with escapes. Delegate that to InEscString + // (unless there ARE no escapes). + boost::scoped_ptr< LLStringUtilBaseImpl::InString<T> > instrp; + if (escapes.empty()) + instrp.reset(new LLStringUtilBaseImpl::InString<T>(string.begin(), string.end())); + else + instrp.reset(new LLStringUtilBaseImpl::InEscString<T>(string.begin(), string.end(), escapes)); + LLStringUtilBaseImpl::getTokens(*instrp, tokens, drop_delims, keep_delims, quotes); +} // static template<class T> @@ -669,7 +1035,7 @@ S32 LLStringUtilBase<T>::compareStrings(const T* lhs, const T* rhs) //static template<class T> -S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs) +S32 LLStringUtilBase<T>::compareStrings(const string_type& lhs, const string_type& rhs) { return LLStringOps::collate(lhs.c_str(), rhs.c_str()); } @@ -695,8 +1061,8 @@ S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs ) } else { - std::basic_string<T> lhs_string(lhs); - std::basic_string<T> rhs_string(rhs); + string_type lhs_string(lhs); + string_type rhs_string(rhs); LLStringUtilBase<T>::toUpper(lhs_string); LLStringUtilBase<T>::toUpper(rhs_string); result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); @@ -706,10 +1072,10 @@ S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs ) //static template<class T> -S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs) +S32 LLStringUtilBase<T>::compareInsensitive(const string_type& lhs, const string_type& rhs) { - std::basic_string<T> lhs_string(lhs); - std::basic_string<T> rhs_string(rhs); + string_type lhs_string(lhs); + string_type rhs_string(rhs); LLStringUtilBase<T>::toUpper(lhs_string); LLStringUtilBase<T>::toUpper(rhs_string); return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); @@ -720,7 +1086,7 @@ S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, con //static template<class T> -S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr) +S32 LLStringUtilBase<T>::compareDict(const string_type& astr, const string_type& bstr) { const T* a = astr.c_str(); const T* b = bstr.c_str(); @@ -761,7 +1127,7 @@ S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std // static template<class T> -S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr) +S32 LLStringUtilBase<T>::compareDictInsensitive(const string_type& astr, const string_type& bstr) { const T* a = astr.c_str(); const T* b = bstr.c_str(); @@ -796,7 +1162,7 @@ S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr // Puts compareDict() in a form appropriate for LL container classes to use for sorting. // static template<class T> -BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b ) +BOOL LLStringUtilBase<T>::precedesDict( const string_type& a, const string_type& b ) { if( a.size() && b.size() ) { @@ -810,7 +1176,7 @@ BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std //static template<class T> -void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string) +void LLStringUtilBase<T>::toUpper(string_type& string) { if( !string.empty() ) { @@ -824,7 +1190,7 @@ void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string) //static template<class T> -void LLStringUtilBase<T>::toLower(std::basic_string<T>& string) +void LLStringUtilBase<T>::toLower(string_type& string) { if( !string.empty() ) { @@ -838,7 +1204,7 @@ void LLStringUtilBase<T>::toLower(std::basic_string<T>& string) //static template<class T> -void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string) +void LLStringUtilBase<T>::trimHead(string_type& string) { if( !string.empty() ) { @@ -853,7 +1219,7 @@ void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string) //static template<class T> -void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string) +void LLStringUtilBase<T>::trimTail(string_type& string) { if( string.size() ) { @@ -872,7 +1238,7 @@ void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string) // Replace line feeds with carriage return-line feed pairs. //static template<class T> -void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string) +void LLStringUtilBase<T>::addCRLF(string_type& string) { const T LF = 10; const T CR = 13; @@ -914,7 +1280,7 @@ void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string) // Remove all carriage returns //static template<class T> -void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string) +void LLStringUtilBase<T>::removeCRLF(string_type& string) { const T CR = 13; @@ -935,10 +1301,10 @@ void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string) //static template<class T> -void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement ) +void LLStringUtilBase<T>::replaceChar( string_type& string, T target, T replacement ) { size_type found_pos = 0; - while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) + while( (found_pos = string.find(target, found_pos)) != string_type::npos ) { string[found_pos] = replacement; found_pos++; // avoid infinite defeat if target == replacement @@ -947,10 +1313,10 @@ void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T //static template<class T> -void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement ) +void LLStringUtilBase<T>::replaceString( string_type& string, string_type target, string_type replacement ) { size_type found_pos = 0; - while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) + while( (found_pos = string.find(target, found_pos)) != string_type::npos ) { string.replace( found_pos, target.length(), replacement ); found_pos += replacement.length(); // avoid infinite defeat if replacement contains target @@ -959,7 +1325,7 @@ void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basi //static template<class T> -void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement ) +void LLStringUtilBase<T>::replaceNonstandardASCII( string_type& string, T replacement ) { const char LF = 10; const S8 MIN = 32; @@ -979,12 +1345,12 @@ void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, //static template<class T> -void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab ) +void LLStringUtilBase<T>::replaceTabsWithSpaces( string_type& str, size_type spaces_per_tab ) { const T TAB = '\t'; const T SPACE = ' '; - std::basic_string<T> out_str; + string_type out_str; // Replace tabs with spaces for (size_type i = 0; i < str.length(); i++) { @@ -1003,7 +1369,7 @@ void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size //static template<class T> -BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& string) +BOOL LLStringUtilBase<T>::containsNonprintable(const string_type& string) { const char MIN = 32; BOOL rv = FALSE; @@ -1020,7 +1386,7 @@ BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& strin //static template<class T> -void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string) +void LLStringUtilBase<T>::stripNonprintable(string_type& string) { const char MIN = 32; size_type j = 0; @@ -1051,8 +1417,43 @@ void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string) delete []c_string; } +template<class T> +std::basic_string<T> LLStringUtilBase<T>::quote(const string_type& str, + const string_type& triggers, + const string_type& escape) +{ + size_type len(str.length()); + // If the string is already quoted, assume user knows what s/he's doing. + if (len >= 2 && str[0] == '"' && str[len-1] == '"') + { + return str; + } + + // Not already quoted: do we need to? triggers.empty() is a special case + // meaning "always quote." + if ((! triggers.empty()) && str.find_first_of(triggers) == string_type::npos) + { + // no trigger characters, don't bother quoting + return str; + } + + // For whatever reason, we must quote this string. + string_type result; + result.push_back('"'); + for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci) + { + if (*ci == '"') + { + result.append(escape); + } + result.push_back(*ci); + } + result.push_back('"'); + return result; +} + template<class T> -void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& string) +void LLStringUtilBase<T>::_makeASCII(string_type& string) { // Replace non-ASCII chars with LL_UNKNOWN_CHAR for (size_type i = 0; i < string.length(); i++) @@ -1082,7 +1483,7 @@ void LLStringUtilBase<T>::copy( T* dst, const T* src, size_type dst_size ) // static template<class T> -void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset) +void LLStringUtilBase<T>::copyInto(string_type& dst, const string_type& src, size_type offset) { if ( offset == dst.length() ) { @@ -1092,7 +1493,7 @@ void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_s } else { - std::basic_string<T> tail = dst.substr(offset); + string_type tail = dst.substr(offset); dst = dst.substr(0, offset); dst += src; @@ -1103,7 +1504,7 @@ void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_s // True if this is the head of s. //static template<class T> -BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s ) +BOOL LLStringUtilBase<T>::isHead( const string_type& string, const T* s ) { if( string.empty() ) { @@ -1119,8 +1520,8 @@ BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s // static template<class T> bool LLStringUtilBase<T>::startsWith( - const std::basic_string<T>& string, - const std::basic_string<T>& substr) + const string_type& string, + const string_type& substr) { if(string.empty() || (substr.empty())) return false; if(0 == string.find(substr)) return true; @@ -1130,8 +1531,8 @@ bool LLStringUtilBase<T>::startsWith( // static template<class T> bool LLStringUtilBase<T>::endsWith( - const std::basic_string<T>& string, - const std::basic_string<T>& substr) + const string_type& string, + const string_type& substr) { if(string.empty() || (substr.empty())) return false; std::string::size_type idx = string.rfind(substr); @@ -1141,14 +1542,14 @@ bool LLStringUtilBase<T>::endsWith( template<class T> -BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value) +BOOL LLStringUtilBase<T>::convertToBOOL(const string_type& string, BOOL& value) { if( string.empty() ) { return FALSE; } - std::basic_string<T> temp( string ); + string_type temp( string ); trim(temp); if( (temp == "1") || @@ -1178,7 +1579,7 @@ BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL } template<class T> -BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& value) +BOOL LLStringUtilBase<T>::convertToU8(const string_type& string, U8& value) { S32 value32 = 0; BOOL success = convertToS32(string, value32); @@ -1191,7 +1592,7 @@ BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& va } template<class T> -BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& value) +BOOL LLStringUtilBase<T>::convertToS8(const string_type& string, S8& value) { S32 value32 = 0; BOOL success = convertToS32(string, value32); @@ -1204,7 +1605,7 @@ BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& va } template<class T> -BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16& value) +BOOL LLStringUtilBase<T>::convertToS16(const string_type& string, S16& value) { S32 value32 = 0; BOOL success = convertToS32(string, value32); @@ -1217,7 +1618,7 @@ BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16& } template<class T> -BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16& value) +BOOL LLStringUtilBase<T>::convertToU16(const string_type& string, U16& value) { S32 value32 = 0; BOOL success = convertToS32(string, value32); @@ -1230,17 +1631,17 @@ BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16& } template<class T> -BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& value) +BOOL LLStringUtilBase<T>::convertToU32(const string_type& string, U32& value) { if( string.empty() ) { return FALSE; } - std::basic_string<T> temp( string ); + string_type temp( string ); trim(temp); U32 v; - std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); + std::basic_istringstream<T> i_stream((string_type)temp); if(i_stream >> v) { value = v; @@ -1250,17 +1651,17 @@ BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& } template<class T> -BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value) +BOOL LLStringUtilBase<T>::convertToS32(const string_type& string, S32& value) { if( string.empty() ) { return FALSE; } - std::basic_string<T> temp( string ); + string_type temp( string ); trim(temp); S32 v; - std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); + std::basic_istringstream<T> i_stream((string_type)temp); if(i_stream >> v) { //TODO: figure out overflow and underflow reporting here @@ -1277,7 +1678,7 @@ BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& } template<class T> -BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32& value) +BOOL LLStringUtilBase<T>::convertToF32(const string_type& string, F32& value) { F64 value64 = 0.0; BOOL success = convertToF64(string, value64); @@ -1290,17 +1691,17 @@ BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32& } template<class T> -BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64& value) +BOOL LLStringUtilBase<T>::convertToF64(const string_type& string, F64& value) { if( string.empty() ) { return FALSE; } - std::basic_string<T> temp( string ); + string_type temp( string ); trim(temp); F64 v; - std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); + std::basic_istringstream<T> i_stream((string_type)temp); if(i_stream >> v) { //TODO: figure out overflow and underflow reporting here @@ -1317,7 +1718,7 @@ BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64& } template<class T> -void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count) +void LLStringUtilBase<T>::truncate(string_type& string, size_type count) { size_type cur_size = string.size(); string.resize(count < cur_size ? count : cur_size); diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 38054b636e..9ebc6de7f4 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -83,7 +83,7 @@ U32 micro_sleep(U64 us, U32 max_yields) { // max_yields is unused; just fiddle with it to avoid warnings. max_yields = 0; - ms_sleep(us / 1000); + ms_sleep((U32)(us / 1000)); return 0; } #elif LL_LINUX || LL_SOLARIS || LL_DARWIN diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h new file mode 100644 index 0000000000..7510cc12ed --- /dev/null +++ b/indra/llcommon/lltypeinfolookup.h @@ -0,0 +1,110 @@ +/** + * @file lltypeinfolookup.h + * @author Nat Goodspeed + * @date 2012-04-08 + * @brief Template data structure like std::map<std::type_info*, T> + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLTYPEINFOLOOKUP_H) +#define LL_LLTYPEINFOLOOKUP_H + +#include "llsortedvector.h" +#include <typeinfo> + +/** + * LLTypeInfoLookup is specifically designed for use cases for which you might + * consider std::map<std::type_info*, VALUE>. We have several such data + * structures in the viewer. The trouble with them is that at least on Linux, + * you can't rely on always getting the same std::type_info* for a given type: + * different load modules will produce different std::type_info*. + * LLTypeInfoLookup contains a workaround to address this issue. + * + * Specifically, when we don't find the passed std::type_info*, + * LLTypeInfoLookup performs a linear search over registered entries to + * compare name() strings. Presuming that this succeeds, we cache the new + * (previously unrecognized) std::type_info* to speed future lookups. + * + * This worst-case fallback search (linear search with string comparison) + * should only happen the first time we look up a given type from a particular + * load module other than the one from which we initially registered types. + * (However, a lookup which wouldn't succeed anyway will always have + * worst-case performance.) This class is probably best used with less than a + * few dozen different types. + */ +template <typename VALUE> +class LLTypeInfoLookup +{ +public: + typedef LLTypeInfoLookup<VALUE> self; + typedef LLSortedVector<const std::type_info*, VALUE> vector_type; + typedef typename vector_type::key_type key_type; + typedef typename vector_type::mapped_type mapped_type; + typedef typename vector_type::value_type value_type; + typedef typename vector_type::iterator iterator; + typedef typename vector_type::const_iterator const_iterator; + + LLTypeInfoLookup() {} + + iterator begin() { return mVector.begin(); } + iterator end() { return mVector.end(); } + const_iterator begin() const { return mVector.begin(); } + const_iterator end() const { return mVector.end(); } + bool empty() const { return mVector.empty(); } + std::size_t size() const { return mVector.size(); } + + std::pair<iterator, bool> insert(const std::type_info* key, const VALUE& value) + { + return insert(value_type(key, value)); + } + + std::pair<iterator, bool> insert(const value_type& pair) + { + return mVector.insert(pair); + } + + // const find() forwards to non-const find(): this can alter mVector! + const_iterator find(const std::type_info* key) const + { + return const_cast<self*>(this)->find(key); + } + + // non-const find() caches previously-unknown type_info* to speed future + // lookups. + iterator find(const std::type_info* key) + { + iterator found = mVector.find(key); + if (found != mVector.end()) + { + // If LLSortedVector::find() found, great, we're done. + return found; + } + // Here we didn't find the passed type_info*. On Linux, though, even + // for the same type, typeid(sametype) produces a different type_info* + // when used in different load modules. So the fact that we didn't + // find the type_info* we seek doesn't mean this type isn't + // registered. Scan for matching name() string. + for (typename vector_type::iterator ti(mVector.begin()), tend(mVector.end()); + ti != tend; ++ti) + { + if (std::string(ti->first->name()) == key->name()) + { + // This unrecognized 'key' is for the same type as ti->first. + // To speed future lookups, insert a new entry that lets us + // look up ti->second using this same 'key'. + return insert(key, ti->second).first; + } + } + // We simply have never seen a type with this type_info* from any load + // module. + return mVector.end(); + } + +private: + vector_type mVector; +}; + +#endif /* ! defined(LL_LLTYPEINFOLOOKUP_H) */ diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index a869c74189..22d0aba51b 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 = 0; +const S32 LL_VERSION_PATCH = 4; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llcommon/tests/StringVec.h b/indra/llcommon/tests/StringVec.h new file mode 100644 index 0000000000..a380b00a05 --- /dev/null +++ b/indra/llcommon/tests/StringVec.h @@ -0,0 +1,37 @@ +/** + * @file StringVec.h + * @author Nat Goodspeed + * @date 2012-02-24 + * @brief Extend TUT ensure_equals() to handle std::vector<std::string> + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_STRINGVEC_H) +#define LL_STRINGVEC_H + +#include <vector> +#include <string> +#include <iostream> + +typedef std::vector<std::string> StringVec; + +std::ostream& operator<<(std::ostream& out, const StringVec& strings) +{ + out << '('; + StringVec::const_iterator begin(strings.begin()), end(strings.end()); + if (begin != end) + { + out << '"' << *begin << '"'; + while (++begin != end) + { + out << ", \"" << *begin << '"'; + } + } + out << ')'; + return out; +} + +#endif /* ! defined(LL_STRINGVEC_H) */ diff --git a/indra/llcommon/tests/listener.h b/indra/llcommon/tests/listener.h index dcdb2412be..9c5c18a150 100644 --- a/indra/llcommon/tests/listener.h +++ b/indra/llcommon/tests/listener.h @@ -30,6 +30,8 @@ #define LL_LISTENER_H #include "llsd.h" +#include "llevents.h" +#include "tests/StringVec.h" #include <iostream> /***************************************************************************** @@ -133,24 +135,7 @@ struct Collect return false; } void clear() { result.clear(); } - typedef std::vector<std::string> StringList; - StringList result; + StringVec result; }; -std::ostream& operator<<(std::ostream& out, const Collect::StringList& strings) -{ - out << '('; - Collect::StringList::const_iterator begin(strings.begin()), end(strings.end()); - if (begin != end) - { - out << '"' << *begin << '"'; - while (++begin != end) - { - out << ", \"" << *begin << '"'; - } - } - out << ')'; - return out; -} - #endif /* ! defined(LL_LISTENER_H) */ diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 09a20231de..279a90e51b 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llerror_test.cpp * @date December 2006 * @brief error unit tests @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2006&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$ */ @@ -49,7 +49,7 @@ namespace static bool fatalWasCalled; void fatalCall(const std::string&) { fatalWasCalled = true; } } - + namespace tut { class TestRecorder : public LLError::Recorder @@ -57,59 +57,65 @@ namespace tut public: TestRecorder() : mWantsTime(false) { } ~TestRecorder() { LLError::removeRecorder(this); } - + void recordMessage(LLError::ELevel level, const std::string& message) { mMessages.push_back(message); } - + int countMessages() { return (int) mMessages.size(); } void clearMessages() { mMessages.clear(); } - + void setWantsTime(bool t) { mWantsTime = t; } bool wantsTime() { return mWantsTime; } - + std::string message(int n) { std::ostringstream test_name; test_name << "testing message " << n << ", not enough messages"; - + tut::ensure(test_name.str(), n < countMessages()); return mMessages[n]; } - + private: typedef std::vector<std::string> MessageVector; MessageVector mMessages; - + bool mWantsTime; }; struct ErrorTestData { - TestRecorder mRecorder; + // addRecorder() expects to be able to later delete the passed + // Recorder*. Even though removeRecorder() reclaims ownership, passing + // a pointer to a data member rather than a heap Recorder subclass + // instance would just be Wrong. + TestRecorder* mRecorder; LLError::Settings* mPriorErrorSettings; - - ErrorTestData() + + ErrorTestData(): + mRecorder(new TestRecorder) { fatalWasCalled = false; - + mPriorErrorSettings = LLError::saveAndResetSettings(); LLError::setDefaultLevel(LLError::LEVEL_DEBUG); LLError::setFatalFunction(fatalCall); - LLError::addRecorder(&mRecorder); + LLError::addRecorder(mRecorder); } - + ~ErrorTestData() { - LLError::removeRecorder(&mRecorder); + LLError::removeRecorder(mRecorder); + delete mRecorder; LLError::restoreSettings(mPriorErrorSettings); } - + void ensure_message_count(int expectedCount) { - ensure_equals("message count", mRecorder.countMessages(), expectedCount); + ensure_equals("message count", mRecorder->countMessages(), expectedCount); } void ensure_message_contains(int n, const std::string& expectedText) @@ -117,7 +123,7 @@ namespace tut std::ostringstream test_name; test_name << "testing message " << n; - ensure_contains(test_name.str(), mRecorder.message(n), expectedText); + ensure_contains(test_name.str(), mRecorder->message(n), expectedText); } void ensure_message_does_not_contain(int n, const std::string& expectedText) @@ -125,22 +131,22 @@ namespace tut std::ostringstream test_name; test_name << "testing message " << n; - ensure_does_not_contain(test_name.str(), mRecorder.message(n), expectedText); + ensure_does_not_contain(test_name.str(), mRecorder->message(n), expectedText); } }; - + typedef test_group<ErrorTestData> ErrorTestGroup; typedef ErrorTestGroup::object ErrorTestObject; - + ErrorTestGroup errorTestGroup("error"); - + template<> template<> void ErrorTestObject::test<1>() // basic test of output { llinfos << "test" << llendl; llinfos << "bob" << llendl; - + ensure_message_contains(0, "test"); ensure_message_contains(1, "bob"); } @@ -159,7 +165,7 @@ namespace }; namespace tut -{ +{ template<> template<> void ErrorTestObject::test<2>() // messages are filtered based on default level @@ -172,7 +178,7 @@ namespace tut ensure_message_contains(3, "error"); ensure_message_contains(4, "four"); ensure_message_count(5); - + LLError::setDefaultLevel(LLError::LEVEL_INFO); writeSome(); ensure_message_contains(5, "two"); @@ -180,20 +186,20 @@ namespace tut ensure_message_contains(7, "error"); ensure_message_contains(8, "four"); ensure_message_count(9); - + LLError::setDefaultLevel(LLError::LEVEL_WARN); writeSome(); ensure_message_contains(9, "three"); ensure_message_contains(10, "error"); ensure_message_contains(11, "four"); ensure_message_count(12); - + LLError::setDefaultLevel(LLError::LEVEL_ERROR); writeSome(); ensure_message_contains(12, "error"); ensure_message_contains(13, "four"); ensure_message_count(14); - + LLError::setDefaultLevel(LLError::LEVEL_NONE); writeSome(); ensure_message_count(14); @@ -218,14 +224,14 @@ namespace tut { std::string thisFile = __FILE__; std::string abbreviateFile = LLError::abbreviateFile(thisFile); - + ensure_ends_with("file name abbreviation", abbreviateFile, "llcommon/tests/llerror_test.cpp" ); ensure_does_not_contain("file name abbreviation", abbreviateFile, "indra"); - + std::string someFile = #if LL_WINDOWS "C:/amy/bob/cam.cpp" @@ -234,12 +240,12 @@ namespace tut #endif ; std::string someAbbreviation = LLError::abbreviateFile(someFile); - + ensure_equals("non-indra file abbreviation", someAbbreviation, someFile); } } - + namespace { std::string locationString(int line) @@ -247,22 +253,22 @@ namespace std::ostringstream location; location << LLError::abbreviateFile(__FILE__) << "(" << line << ") : "; - + return location.str(); } - + std::string writeReturningLocation() { llinfos << "apple" << llendl; int this_line = __LINE__; return locationString(this_line); } - + std::string writeReturningLocationAndFunction() { llinfos << "apple" << llendl; int this_line = __LINE__; return locationString(this_line) + __FUNCTION__; } - + std::string errorReturningLocation() { llerrs << "die" << llendl; int this_line = __LINE__; @@ -271,20 +277,20 @@ namespace } namespace tut -{ +{ template<> template<> void ErrorTestObject::test<5>() // file and line information in log messages { std::string location = writeReturningLocation(); // expecting default to not print location information - + LLError::setPrintLocation(true); writeReturningLocation(); - + LLError::setPrintLocation(false); writeReturningLocation(); - + ensure_message_does_not_contain(0, location); ensure_message_contains(1, location); ensure_message_does_not_contain(2, location); @@ -297,7 +303,7 @@ namespace tut existing log messages often do.) The functions all return their C++ name so that test can be substantial mechanized. */ - + std::string logFromGlobal(bool id) { llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl; @@ -345,7 +351,7 @@ namespace return "ClassWithNoLogType::logFromStatic"; } }; - + class ClassWithLogType { LOG_CLASS(ClassWithLogType); public: @@ -360,13 +366,13 @@ namespace return "ClassWithLogType::logFromStatic"; } }; - + std::string logFromNamespace(bool id) { return Foo::logFromNamespace(id); } std::string logFromClassWithNoLogTypeMember(bool id) { ClassWithNoLogType c; return c.logFromMember(id); } std::string logFromClassWithNoLogTypeStatic(bool id) { return ClassWithNoLogType::logFromStatic(id); } std::string logFromClassWithLogTypeMember(bool id) { ClassWithLogType c; return c.logFromMember(id); } std::string logFromClassWithLogTypeStatic(bool id) { return ClassWithLogType::logFromStatic(id); } - + void ensure_has(const std::string& message, const std::string& actual, const std::string& expected) { @@ -379,18 +385,18 @@ namespace throw tut::failure(ss.str().c_str()); } } - + typedef std::string (*LogFromFunction)(bool); - void testLogName(tut::TestRecorder& recorder, LogFromFunction f, + void testLogName(tut::TestRecorder* recorder, LogFromFunction f, const std::string& class_name = "") { - recorder.clearMessages(); + recorder->clearMessages(); std::string name = f(false); f(true); - - std::string messageWithoutName = recorder.message(0); - std::string messageWithName = recorder.message(1); - + + std::string messageWithoutName = recorder->message(0); + std::string messageWithName = recorder->message(1); + ensure_has(name + " logged without name", messageWithoutName, name); ensure_has(name + " logged with name", @@ -431,18 +437,18 @@ namespace llinfos << "inside" << llendl; return "moo"; } - + std::string outerLogger() { llinfos << "outside(" << innerLogger() << ")" << llendl; return "bar"; } - + void uberLogger() { llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl; } - + class LogWhileLogging { public: @@ -461,11 +467,11 @@ namespace LogWhileLogging l; llinfos << "meta(" << l << ")" << llendl; } - + } namespace tut -{ +{ template<> template<> // handle nested logging void ErrorTestObject::test<7>() @@ -474,31 +480,31 @@ namespace tut ensure_message_contains(0, "inside"); ensure_message_contains(1, "outside(moo)"); ensure_message_count(2); - + uberLogger(); ensure_message_contains(2, "inside"); ensure_message_contains(3, "inside"); ensure_message_contains(4, "outside(moo)"); ensure_message_contains(5, "uber(bar,moo)"); ensure_message_count(6); - + metaLogger(); ensure_message_contains(6, "logging"); ensure_message_contains(7, "meta(baz)"); ensure_message_count(8); } - + template<> template<> // special handling of llerrs calls void ErrorTestObject::test<8>() { LLError::setPrintLocation(false); std::string location = errorReturningLocation(); - + ensure_message_contains(0, location + "error"); ensure_message_contains(1, "die"); ensure_message_count(2); - + ensure("fatal callback called", fatalWasCalled); } } @@ -509,7 +515,7 @@ namespace { return "1947-07-08T03:04:05Z"; } - + void ufoSighting() { llinfos << "ufo" << llendl; @@ -517,35 +523,35 @@ namespace } namespace tut -{ +{ template<> template<> // time in output (for recorders that need it) void ErrorTestObject::test<9>() { LLError::setTimeFunction(roswell); - mRecorder.setWantsTime(false); + mRecorder->setWantsTime(false); ufoSighting(); ensure_message_contains(0, "ufo"); ensure_message_does_not_contain(0, roswell()); - - mRecorder.setWantsTime(true); + + mRecorder->setWantsTime(true); ufoSighting(); ensure_message_contains(1, "ufo"); ensure_message_contains(1, roswell()); } - + template<> template<> // output order void ErrorTestObject::test<10>() { LLError::setPrintLocation(true); LLError::setTimeFunction(roswell); - mRecorder.setWantsTime(true); + mRecorder->setWantsTime(true); std::string locationAndFunction = writeReturningLocationAndFunction(); - + ensure_equals("order is time type location function message", - mRecorder.message(0), + mRecorder->message(0), roswell() + " INFO: " + locationAndFunction + ": apple"); } @@ -553,30 +559,30 @@ namespace tut // multiple recorders void ErrorTestObject::test<11>() { - TestRecorder altRecorder; - LLError::addRecorder(&altRecorder); - + TestRecorder* altRecorder(new TestRecorder); + LLError::addRecorder(altRecorder); + llinfos << "boo" << llendl; ensure_message_contains(0, "boo"); - ensure_equals("alt recorder count", altRecorder.countMessages(), 1); - ensure_contains("alt recorder message 0", altRecorder.message(0), "boo"); - + ensure_equals("alt recorder count", altRecorder->countMessages(), 1); + ensure_contains("alt recorder message 0", altRecorder->message(0), "boo"); + LLError::setTimeFunction(roswell); - TestRecorder anotherRecorder; - anotherRecorder.setWantsTime(true); - LLError::addRecorder(&anotherRecorder); - + TestRecorder* anotherRecorder(new TestRecorder); + anotherRecorder->setWantsTime(true); + LLError::addRecorder(anotherRecorder); + llinfos << "baz" << llendl; std::string when = roswell(); - + ensure_message_does_not_contain(1, when); - ensure_equals("alt recorder count", altRecorder.countMessages(), 2); - ensure_does_not_contain("alt recorder message 1", altRecorder.message(1), when); - ensure_equals("another recorder count", anotherRecorder.countMessages(), 1); - ensure_contains("another recorder message 0", anotherRecorder.message(0), when); + ensure_equals("alt recorder count", altRecorder->countMessages(), 2); + ensure_does_not_contain("alt recorder message 1", altRecorder->message(1), when); + ensure_equals("another recorder count", anotherRecorder->countMessages(), 1); + ensure_contains("another recorder message 0", anotherRecorder->message(0), when); } } @@ -610,10 +616,10 @@ namespace tut { LLError::setDefaultLevel(LLError::LEVEL_WARN); LLError::setClassLevel("TestBeta", LLError::LEVEL_INFO); - + TestAlpha::doAll(); TestBeta::doAll(); - + ensure_message_contains(0, "aim west"); ensure_message_contains(1, "error"); ensure_message_contains(2, "ate eels"); @@ -623,7 +629,7 @@ namespace tut ensure_message_contains(6, "big easy"); ensure_message_count(7); } - + template<> template<> // filtering by function, and that it will override class filtering void ErrorTestObject::test<13>() @@ -632,13 +638,13 @@ namespace tut LLError::setClassLevel("TestBeta", LLError::LEVEL_WARN); LLError::setFunctionLevel("TestBeta::doInfo", LLError::LEVEL_DEBUG); LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE); - + TestBeta::doAll(); ensure_message_contains(0, "buy iron"); ensure_message_contains(1, "bad word"); ensure_message_count(2); } - + template<> template<> // filtering by file // and that it is overridden by both class and function filtering @@ -652,7 +658,7 @@ namespace tut LLError::LEVEL_NONE); LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE); - + TestAlpha::doAll(); TestBeta::doAll(); ensure_message_contains(0, "any idea"); @@ -660,7 +666,7 @@ namespace tut ensure_message_contains(2, "bad word"); ensure_message_count(3); } - + template<> template<> // proper cached, efficient lookup of filtering void ErrorTestObject::test<15>() @@ -690,7 +696,7 @@ namespace tut ensure_message_count(2); ensure_equals("sixth check", LLError::shouldLogCallCount(), 3); } - + template<> template<> // configuration from LLSD void ErrorTestObject::test<16>() @@ -699,26 +705,26 @@ namespace tut LLSD config; config["print-location"] = true; config["default-level"] = "DEBUG"; - + LLSD set1; set1["level"] = "WARN"; set1["files"][0] = this_file; - + LLSD set2; set2["level"] = "INFO"; set2["classes"][0] = "TestAlpha"; - + LLSD set3; set3["level"] = "NONE"; set3["functions"][0] = "TestAlpha::doError"; set3["functions"][1] = "TestBeta::doError"; - + config["settings"][0] = set1; config["settings"][1] = set2; config["settings"][2] = set3; - + LLError::configure(config); - + TestAlpha::doAll(); TestBeta::doAll(); ensure_message_contains(0, "any idea"); @@ -726,13 +732,13 @@ namespace tut ensure_message_contains(1, "aim west"); ensure_message_contains(2, "bad word"); ensure_message_count(3); - + // make sure reconfiguring works LLSD config2; config2["default-level"] = "WARN"; - + LLError::configure(config2); - + TestAlpha::doAll(); TestBeta::doAll(); ensure_message_contains(3, "aim west"); @@ -744,13 +750,13 @@ namespace tut ensure_message_contains(8, "big easy"); ensure_message_count(9); } -} +} /* Tests left: handling of classes without LOG_CLASS - live update of filtering from file - + live update of filtering from file + syslog recorder file recorder cerr/stderr recorder diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index b34d1c5fd3..454695ff9f 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -35,6 +35,7 @@ #include <vector> #include <set> #include <algorithm> // std::sort() +#include <stdexcept> // std headers // external library headers #include <boost/scoped_ptr.hpp> @@ -42,6 +43,11 @@ #include "../test/lltut.h" #include "wrapllerrs.h" +struct Badness: public std::runtime_error +{ + Badness(const std::string& what): std::runtime_error(what) {} +}; + struct Keyed: public LLInstanceTracker<Keyed, std::string> { Keyed(const std::string& name): @@ -53,6 +59,17 @@ struct Keyed: public LLInstanceTracker<Keyed, std::string> struct Unkeyed: public LLInstanceTracker<Unkeyed> { + Unkeyed(const std::string& thrw="") + { + // LLInstanceTracker should respond appropriately if a subclass + // constructor throws an exception. Specifically, it should run + // LLInstanceTracker's destructor and remove itself from the + // underlying container. + if (! thrw.empty()) + { + throw Badness(thrw); + } + } }; /***************************************************************************** @@ -95,6 +112,7 @@ namespace tut void object::test<2>() { ensure_equals(Unkeyed::instanceCount(), 0); + Unkeyed* dangling = NULL; { Unkeyed one; ensure_equals(Unkeyed::instanceCount(), 1); @@ -107,7 +125,11 @@ namespace tut ensure_equals(found, two.get()); } ensure_equals(Unkeyed::instanceCount(), 1); - } + // store an unwise pointer to a temp Unkeyed instance + dangling = &one; + } // make that instance vanish + // check the now-invalid pointer to the destroyed instance + ensure("getInstance(T*) failed to track destruction", ! Unkeyed::getInstance(dangling)); ensure_equals(Unkeyed::instanceCount(), 0); } @@ -229,4 +251,49 @@ namespace tut } ensure(! what.empty()); } + + template<> template<> + void object::test<8>() + { + set_test_name("exception in subclass ctor"); + typedef std::set<Unkeyed*> InstanceSet; + InstanceSet existing; + // We can't use the iterator-range InstanceSet constructor because + // beginInstances() returns an iterator that dereferences to an + // Unkeyed&, not an Unkeyed*. + for (Unkeyed::instance_iter uki(Unkeyed::beginInstances()), + ukend(Unkeyed::endInstances()); + uki != ukend; ++uki) + { + existing.insert(&*uki); + } + Unkeyed* puk = NULL; + try + { + // We don't expect the assignment to take place because we expect + // Unkeyed to respond to the non-empty string param by throwing. + // We know the LLInstanceTracker base-class constructor will have + // run before Unkeyed's constructor, therefore the new instance + // will have added itself to the underlying set. The whole + // question is, when Unkeyed's constructor throws, will + // LLInstanceTracker's destructor remove it from the set? I + // realize we're testing the C++ implementation more than + // Unkeyed's implementation, but this seems an important point to + // nail down. + puk = new Unkeyed("throw"); + } + catch (const Badness&) + { + } + // Ensure that every member of the new, updated set of Unkeyed + // instances was also present in the original set. If that's not true, + // it's because our new Unkeyed ended up in the updated set despite + // its constructor exception. + for (Unkeyed::instance_iter uki(Unkeyed::beginInstances()), + ukend(Unkeyed::endInstances()); + uki != ukend; ++uki) + { + ensure("failed to remove instance", existing.find(&*uki) != existing.end()); + } + } } // namespace tut diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp new file mode 100644 index 0000000000..9b755e9ca5 --- /dev/null +++ b/indra/llcommon/tests/llleap_test.cpp @@ -0,0 +1,694 @@ +/** + * @file llleap_test.cpp + * @author Nat Goodspeed + * @date 2012-02-21 + * @brief Test for llleap. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llleap.h" +// STL headers +// std headers +// external library headers +#include <boost/assign/list_of.hpp> +#include <boost/lambda/lambda.hpp> +#include <boost/foreach.hpp> +// other Linden headers +#include "../test/lltut.h" +#include "../test/namedtempfile.h" +#include "../test/manageapr.h" +#include "../test/catch_and_store_what_in.h" +#include "wrapllerrs.h" +#include "llevents.h" +#include "llprocess.h" +#include "stringize.h" +#include "StringVec.h" +#include <functional> + +using boost::assign::list_of; + +static ManageAPR manager; + +StringVec sv(const StringVec& listof) { return listof; } + +#if defined(LL_WINDOWS) +#define sleep(secs) _sleep((secs) * 1000) +#endif + +#if ! LL_WINDOWS +const size_t BUFFERED_LENGTH = 1023*1024; // try wrangling just under a megabyte of data +#else +// "Then there's Windows... sigh." The "very large message" test is flaky in a +// way that seems to point to either the OS (nonblocking writes to pipes) or +// possibly the apr_file_write() function. Poring over log messages reveals +// that at some point along the way apr_file_write() returns 11 (Resource +// temporarily unavailable, i.e. EAGAIN) and says it wrote 0 bytes -- even +// though it did write the chunk! Our next write attempt retries the same +// chunk, resulting in the chunk being duplicated at the child end, corrupting +// the data stream. Much as I would love to be able to fix it for real, such a +// fix would appear to require distinguishing bogus EAGAIN returns from real +// ones -- how?? Empirically this behavior is only observed when writing a +// "very large message". To be able to move forward at all, try to bypass this +// particular failure by adjusting the size of a "very large message" on +// Windows. +const size_t BUFFERED_LENGTH = 65336; +#endif // LL_WINDOWS + +void waitfor(const std::vector<LLLeap*>& instances, int timeout=60) +{ + int i; + for (i = 0; i < timeout; ++i) + { + // Every iteration, test whether any of the passed LLLeap instances + // still exist (are still running). + std::vector<LLLeap*>::const_iterator vli(instances.begin()), vlend(instances.end()); + for ( ; vli != vlend; ++vli) + { + // getInstance() returns NULL if it's terminated/gone, non-NULL if + // it's still running + if (LLLeap::getInstance(*vli)) + break; + } + // If we made it through all of 'instances' without finding one that's + // still running, we're done. + if (vli == vlend) + { +/*==========================================================================*| + std::cout << instances.size() << " LLLeap instances terminated in " + << i << " seconds, proceeding" << std::endl; +|*==========================================================================*/ + return; + } + // Found an instance that's still running. Wait and pump LLProcess. + sleep(1); + LLEventPumps::instance().obtain("mainloop").post(LLSD()); + } + tut::ensure(STRINGIZE("at least 1 of " << instances.size() + << " LLLeap instances timed out (" + << timeout << " seconds) without terminating"), + i < timeout); +} + +void waitfor(LLLeap* instance, int timeout=60) +{ + std::vector<LLLeap*> instances; + instances.push_back(instance); + waitfor(instances, timeout); +} + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llleap_data + { + llleap_data(): + reader(".py", + // This logic is adapted from vita.viewerclient.receiveEvent() + boost::lambda::_1 << + "import re\n" + "import os\n" + "import sys\n" + "\n" + // Don't forget that this Python script is written to some + // temp directory somewhere! Its __file__ is useless in + // finding indra/lib/python. Use our __FILE__, with + // raw-string syntax to deal with Windows pathnames. + "mydir = os.path.dirname(r'" << __FILE__ << "')\n" + "try:\n" + " from llbase import llsd\n" + "except ImportError:\n" + // We expect mydir to be .../indra/llcommon/tests. + " sys.path.insert(0,\n" + " os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n" + " from indra.base import llsd\n" + "\n" + "class ProtocolError(Exception):\n" + " def __init__(self, msg, data):\n" + " Exception.__init__(self, msg)\n" + " self.data = data\n" + "\n" + "class ParseError(ProtocolError):\n" + " pass\n" + "\n" + "def get():\n" + " hdr = ''\n" + " while ':' not in hdr and len(hdr) < 20:\n" + " hdr += sys.stdin.read(1)\n" + " if not hdr:\n" + " sys.exit(0)\n" + " if not hdr.endswith(':'):\n" + " raise ProtocolError('Expected len:data, got %r' % hdr, hdr)\n" + " try:\n" + " length = int(hdr[:-1])\n" + " except ValueError:\n" + " raise ProtocolError('Non-numeric len %r' % hdr[:-1], hdr[:-1])\n" + " parts = []\n" + " received = 0\n" + " while received < length:\n" + " parts.append(sys.stdin.read(length - received))\n" + " received += len(parts[-1])\n" + " data = ''.join(parts)\n" + " assert len(data) == length\n" + " try:\n" + " return llsd.parse(data)\n" + // Seems the old indra.base.llsd module didn't properly + // convert IndexError (from running off end of string) to + // LLSDParseError. + " except (IndexError, llsd.LLSDParseError), e:\n" + " msg = 'Bad received packet (%s)' % e\n" + " print >>sys.stderr, '%s, %s bytes:' % (msg, len(data))\n" + " showmax = 40\n" + // We've observed failures with very large packets; + // dumping the entire packet wastes time and space. + // But if the error states a particular byte offset, + // truncate to (near) that offset when dumping data. + " location = re.search(r' at (byte|index) ([0-9]+)', str(e))\n" + " if not location:\n" + " # didn't find offset, dump whole thing, no ellipsis\n" + " ellipsis = ''\n" + " else:\n" + " # found offset within error message\n" + " trunc = int(location.group(2)) + showmax\n" + " data = data[:trunc]\n" + " ellipsis = '... (%s more)' % (length - trunc)\n" + " offset = -showmax\n" + " for offset in xrange(0, len(data)-showmax, showmax):\n" + " print >>sys.stderr, '%04d: %r +' % \\\n" + " (offset, data[offset:offset+showmax])\n" + " offset += showmax\n" + " print >>sys.stderr, '%04d: %r%s' % \\\n" + " (offset, data[offset:], ellipsis)\n" + " raise ParseError(msg, data)\n" + "\n" + "# deal with initial stdin message\n" + // this will throw if the initial write to stdin doesn't + // follow len:data protocol, or if we couldn't find 'pump' + // in the dict + "_reply = get()['pump']\n" + "\n" + "def replypump():\n" + " return _reply\n" + "\n" + "def put(req):\n" + " sys.stdout.write(':'.join((str(len(req)), req)))\n" + " sys.stdout.flush()\n" + "\n" + "def send(pump, data):\n" + " put(llsd.format_notation(dict(pump=pump, data=data)))\n" + "\n" + "def request(pump, data):\n" + " # we expect 'data' is a dict\n" + " data['reply'] = _reply\n" + " send(pump, data)\n"), + // Get the actual pathname of the NamedExtTempFile and trim off + // the ".py" extension. (We could cache reader.getName() in a + // separate member variable, but I happen to know getName() just + // returns a NamedExtTempFile member rather than performing any + // computation, so I don't mind calling it twice.) Then take the + // basename. + reader_module(LLProcess::basename( + reader.getName().substr(0, reader.getName().length()-3))), + pPYTHON(getenv("PYTHON")), + PYTHON(pPYTHON? pPYTHON : "") + { + ensure("Set PYTHON to interpreter pathname", pPYTHON); + } + NamedExtTempFile reader; + const std::string reader_module; + const char* pPYTHON; + const std::string PYTHON; + }; + typedef test_group<llleap_data> llleap_group; + typedef llleap_group::object object; + llleap_group llleapgrp("llleap"); + + template<> template<> + void object::test<1>() + { + set_test_name("multiple LLLeap instances"); + NamedTempFile script("py", + "import time\n" + "time.sleep(1)\n"); + std::vector<LLLeap*> instances; + instances.push_back(LLLeap::create(get_test_name(), + sv(list_of(PYTHON)(script.getName())))); + instances.push_back(LLLeap::create(get_test_name(), + sv(list_of(PYTHON)(script.getName())))); + // In this case we're simply establishing that two LLLeap instances + // can coexist without throwing exceptions or bombing in any other + // way. Wait for them to terminate. + waitfor(instances); + } + + template<> template<> + void object::test<2>() + { + set_test_name("stderr to log"); + NamedTempFile script("py", + "import sys\n" + "sys.stderr.write('''Hello from Python!\n" + "note partial line''')\n"); + CaptureLog log(LLError::LEVEL_INFO); + waitfor(LLLeap::create(get_test_name(), + sv(list_of(PYTHON)(script.getName())))); + log.messageWith("Hello from Python!"); + log.messageWith("note partial line"); + } + + template<> template<> + void object::test<3>() + { + set_test_name("bad stdout protocol"); + NamedTempFile script("py", + "print 'Hello from Python!'\n"); + CaptureLog log(LLError::LEVEL_WARN); + waitfor(LLLeap::create(get_test_name(), + sv(list_of(PYTHON)(script.getName())))); + ensure_contains("error log line", + log.messageWith("invalid protocol"), "Hello from Python!"); + } + + template<> template<> + void object::test<4>() + { + set_test_name("leftover stdout"); + NamedTempFile script("py", + "import sys\n" + // note lack of newline + "sys.stdout.write('Hello from Python!')\n"); + CaptureLog log(LLError::LEVEL_WARN); + waitfor(LLLeap::create(get_test_name(), + sv(list_of(PYTHON)(script.getName())))); + ensure_contains("error log line", + log.messageWith("Discarding"), "Hello from Python!"); + } + + template<> template<> + void object::test<5>() + { + set_test_name("bad stdout len prefix"); + NamedTempFile script("py", + "import sys\n" + "sys.stdout.write('5a2:something')\n"); + CaptureLog log(LLError::LEVEL_WARN); + waitfor(LLLeap::create(get_test_name(), + sv(list_of(PYTHON)(script.getName())))); + ensure_contains("error log line", + log.messageWith("invalid protocol"), "5a2:"); + } + + template<> template<> + void object::test<6>() + { + set_test_name("empty plugin vector"); + std::string threw; + try + { + LLLeap::create("empty", StringVec()); + } + CATCH_AND_STORE_WHAT_IN(threw, LLLeap::Error) + ensure_contains("LLLeap::Error", threw, "no plugin"); + // try the suppress-exception variant + ensure("bad launch returned non-NULL", ! LLLeap::create("empty", StringVec(), false)); + } + + template<> template<> + void object::test<7>() + { + set_test_name("bad launch"); + // Synthesize bogus executable name + std::string BADPYTHON(PYTHON.substr(0, PYTHON.length()-1) + "x"); + CaptureLog log; + std::string threw; + try + { + LLLeap::create("bad exe", BADPYTHON); + } + CATCH_AND_STORE_WHAT_IN(threw, LLLeap::Error) + ensure_contains("LLLeap::create() didn't throw", threw, "failed"); + log.messageWith("failed"); + log.messageWith(BADPYTHON); + // try the suppress-exception variant + ensure("bad launch returned non-NULL", ! LLLeap::create("bad exe", BADPYTHON, false)); + } + + // Generic self-contained listener: derive from this and override its + // call() method, then tell somebody to post on the pump named getName(). + // Control will reach your call() override. + struct ListenerBase + { + // Pass the pump name you want; will tweak for uniqueness. + ListenerBase(const std::string& name): + mPump(name, true) + { + mPump.listen(name, boost::bind(&ListenerBase::call, this, _1)); + } + + virtual ~ListenerBase() {} // pacify MSVC + + virtual bool call(const LLSD& request) + { + return false; + } + + LLEventPump& getPump() { return mPump; } + const LLEventPump& getPump() const { return mPump; } + + std::string getName() const { return mPump.getName(); } + void post(const LLSD& data) { mPump.post(data); } + + LLEventStream mPump; + }; + + // Mimic a dummy little LLEventAPI that merely sends a reply back to its + // requester on the "reply" pump. + struct AckAPI: public ListenerBase + { + AckAPI(): ListenerBase("AckAPI") {} + + virtual bool call(const LLSD& request) + { + LLEventPumps::instance().obtain(request["reply"]).post("ack"); + return false; + } + }; + + // Give LLLeap script a way to post success/failure. + struct Result: public ListenerBase + { + Result(): ListenerBase("Result") {} + + virtual bool call(const LLSD& request) + { + mData = request; + return false; + } + + void ensure() const + { + tut::ensure(std::string("never posted to ") + getName(), mData.isDefined()); + // Post an empty string for success, non-empty string is failure message. + tut::ensure(mData, mData.asString().empty()); + } + + LLSD mData; + }; + + template<> template<> + void object::test<8>() + { + set_test_name("round trip"); + AckAPI api; + Result result; + NamedTempFile script("py", + boost::lambda::_1 << + "from " << reader_module << " import *\n" + // make a request on our little API + "request(pump='" << api.getName() << "', data={})\n" + // wait for its response + "resp = get()\n" + "result = '' if resp == dict(pump=replypump(), data='ack')\\\n" + " else 'bad: ' + str(resp)\n" + "send(pump='" << result.getName() << "', data=result)\n"); + waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName())))); + result.ensure(); + } + + struct ReqIDAPI: public ListenerBase + { + ReqIDAPI(): ListenerBase("ReqIDAPI") {} + + virtual bool call(const LLSD& request) + { + // free function from llevents.h + sendReply(LLSD(), request); + return false; + } + }; + + template<> template<> + void object::test<9>() + { + set_test_name("many small messages"); + // It's not clear to me whether there's value in iterating many times + // over a send/receive loop -- I don't think that will exercise any + // interesting corner cases. This test first sends a large number of + // messages, then receives all the responses. The intent is to ensure + // that some of that data stream crosses buffer boundaries, loop + // iterations etc. in OS pipes and the LLLeap/LLProcess implementation. + ReqIDAPI api; + Result result; + NamedTempFile script("py", + boost::lambda::_1 << + "import sys\n" + "from " << reader_module << " import *\n" + // Note that since reader imports llsd, this + // 'import *' gets us llsd too. + "sample = llsd.format_notation(dict(pump='" << + api.getName() << "', data=dict(reqid=999999, reply=replypump())))\n" + // The whole packet has length prefix too: "len:data" + "samplen = len(str(len(sample))) + 1 + len(sample)\n" + // guess how many messages it will take to + // accumulate BUFFERED_LENGTH + "count = int(" << BUFFERED_LENGTH << "/samplen)\n" + "print >>sys.stderr, 'Sending %s requests' % count\n" + "for i in xrange(count):\n" + " request('" << api.getName() << "', dict(reqid=i))\n" + // The assumption in this specific test that + // replies will arrive in the same order as + // requests is ONLY valid because the API we're + // invoking sends replies instantly. If the API + // had to wait for some external event before + // sending its reply, replies could arrive in + // arbitrary order, and we'd have to tick them + // off from a set. + "result = ''\n" + "for i in xrange(count):\n" + " resp = get()\n" + " if resp['data']['reqid'] != i:\n" + " result = 'expected reqid=%s in %s' % (i, resp)\n" + " break\n" + "send(pump='" << result.getName() << "', data=result)\n"); + waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName()))), + 300); // needs more realtime than most tests + result.ensure(); + } + + // This is the body of test<10>, extracted so we can run it over a number + // of large-message sizes. + void test_large_message(const std::string& PYTHON, const std::string& reader_module, + const std::string& test_name, size_t size) + { + ReqIDAPI api; + Result result; + NamedTempFile script("py", + boost::lambda::_1 << + "import sys\n" + "from " << reader_module << " import *\n" + // Generate a very large string value. + "desired = int(sys.argv[1])\n" + // 7 chars per item: 6 digits, 1 comma + "count = int((desired - 50)/7)\n" + "large = ''.join('%06d,' % i for i in xrange(count))\n" + // Pass 'large' as reqid because we know the API + // will echo reqid, and we want to receive it back. + "request('" << api.getName() << "', dict(reqid=large))\n" + "try:\n" + " resp = get()\n" + "except ParseError, e:\n" + " # try to find where e.data diverges from expectation\n" + // Normally we'd expect a 'pump' key in there, + // too, with value replypump(). But Python + // serializes keys in a different order than C++, + // so incoming data start with 'data'. + // Truthfully, though, if we get as far as 'pump' + // before we find a difference, something's very + // strange. + " expect = llsd.format_notation(dict(data=dict(reqid=large)))\n" + " chunk = 40\n" + " for offset in xrange(0, max(len(e.data), len(expect)), chunk):\n" + " if e.data[offset:offset+chunk] != \\\n" + " expect[offset:offset+chunk]:\n" + " print >>sys.stderr, 'Offset %06d: expect %r,\\n'\\\n" + " ' get %r' %\\\n" + " (offset,\n" + " expect[offset:offset+chunk],\n" + " e.data[offset:offset+chunk])\n" + " break\n" + " else:\n" + " print >>sys.stderr, 'incoming data matches expect?!'\n" + " send('" << result.getName() << "', '%s: %s' % (e.__class__.__name__, e))\n" + " sys.exit(1)\n" + "\n" + "echoed = resp['data']['reqid']\n" + "if echoed == large:\n" + " send('" << result.getName() << "', '')\n" + " sys.exit(0)\n" + // Here we know echoed did NOT match; try to find where + "for i in xrange(count):\n" + " start = 7*i\n" + " end = 7*(i+1)\n" + " if end > len(echoed)\\\n" + " or echoed[start:end] != large[start:end]:\n" + " send('" << result.getName() << "',\n" + " 'at offset %s, expected %r but got %r' %\n" + " (start, large[start:end], echoed[start:end]))\n" + "sys.exit(1)\n"); + waitfor(LLLeap::create(test_name, + sv(list_of + (PYTHON) + (script.getName()) + (stringize(size)))), + 180); // try a longer timeout + result.ensure(); + } + + struct TestLargeMessage: public std::binary_function<size_t, size_t, bool> + { + TestLargeMessage(const std::string& PYTHON_, const std::string& reader_module_, + const std::string& test_name_): + PYTHON(PYTHON_), + reader_module(reader_module_), + test_name(test_name_) + {} + + bool operator()(size_t left, size_t right) const + { + // We don't know whether upper_bound is going to pass the "sought + // value" as the left or the right operand. We pass 0 as the + // "sought value" so we can distinguish it. Of course that means + // the sequence we're searching must not itself contain 0! + size_t size; + bool success; + if (left) + { + size = left; + // Consider our return value carefully. Normal binary_search + // (or, in our case, upper_bound) expects a container sorted + // in ascending order, and defaults to the std::less + // comparator. Our container is in fact in ascending order, so + // return consistently with std::less. Here we were called as + // compare(item, sought). If std::less were called that way, + // 'true' would mean to move right (to higher numbers) within + // the sequence: the item being considered is less than the + // sought value. For us, that means that test_large_message() + // success should return 'true'. + success = true; + } + else + { + size = right; + // Here we were called as compare(sought, item). If std::less + // were called that way, 'true' would mean to move left (to + // lower numbers) within the sequence: the sought value is + // less than the item being considered. For us, that means + // test_large_message() FAILURE should return 'true', hence + // test_large_message() success should return 'false'. + success = false; + } + + try + { + test_large_message(PYTHON, reader_module, test_name, size); + std::cout << "test_large_message(" << size << ") succeeded" << std::endl; + return success; + } + catch (const failure& e) + { + std::cout << "test_large_message(" << size << ") failed: " << e.what() << std::endl; + return ! success; + } + } + + const std::string PYTHON, reader_module, test_name; + }; + + // The point of this function is to try to find a size at which + // test_large_message() can succeed. We still want the overall test to + // fail; otherwise we won't get the coder's attention -- but if + // test_large_message() fails, try to find a plausible size at which it + // DOES work. + void test_or_split(const std::string& PYTHON, const std::string& reader_module, + const std::string& test_name, size_t size) + { + try + { + test_large_message(PYTHON, reader_module, test_name, size); + } + catch (const failure& e) + { + std::cout << "test_large_message(" << size << ") failed: " << e.what() << std::endl; + // If it still fails below 4K, give up: subdividing any further is + // pointless. + if (size >= 4096) + { + try + { + // Recur with half the size + size_t smaller(size/2); + test_or_split(PYTHON, reader_module, test_name, smaller); + // Recursive call will throw if test_large_message() + // failed, therefore we only reach the line below if it + // succeeded. + std::cout << "but test_large_message(" << smaller << ") succeeded" << std::endl; + + // Binary search for largest size that works. But since + // std::binary_search() only returns bool, actually use + // std::upper_bound(), consistent with our desire to find + // the LARGEST size that works. First generate a sorted + // container of all the sizes we intend to try, from + // 'smaller' (known to work) to 'size' (known to fail). We + // could whomp up magic iterators to do this dynamically, + // without actually instantiating a vector, but for a test + // program this will do. At least preallocate the vector. + // Per TestLargeMessage comments, it's important that this + // vector not contain 0. + std::vector<size_t> sizes; + sizes.reserve((size - smaller)/4096 + 1); + for (size_t sz(smaller), szend(size); sz < szend; sz += 4096) + sizes.push_back(sz); + // our comparator + TestLargeMessage tester(PYTHON, reader_module, test_name); + // Per TestLargeMessage comments, pass 0 as the sought value. + std::vector<size_t>::const_iterator found = + std::upper_bound(sizes.begin(), sizes.end(), 0, tester); + if (found != sizes.end() && found != sizes.begin()) + { + std::cout << "test_large_message(" << *(found - 1) + << ") is largest that succeeds" << std::endl; + } + else + { + std::cout << "cannot determine largest test_large_message(size) " + << "that succeeds" << std::endl; + } + } + catch (const failure&) + { + // The recursive test_or_split() call above has already + // handled the exception. We don't want our caller to see + // innermost exception; propagate outermost (below). + } + } + // In any case, because we reached here through failure of + // our original test_large_message(size) call, ensure failure + // propagates. + throw e; + } + } + + template<> template<> + void object::test<10>() + { + set_test_name("very large message"); + test_or_split(PYTHON, reader_module, get_test_name(), BUFFERED_LENGTH); + } +} // namespace tut diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp new file mode 100644 index 0000000000..99186ed434 --- /dev/null +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -0,0 +1,1262 @@ +/** + * @file llprocess_test.cpp + * @author Nat Goodspeed + * @date 2011-12-19 + * @brief Test for llprocess. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Copyright (c) 2011, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llprocess.h" +// STL headers +#include <vector> +#include <list> +// std headers +#include <fstream> +// external library headers +#include "llapr.h" +#include "apr_thread_proc.h" +#include <boost/foreach.hpp> +#include <boost/function.hpp> +#include <boost/algorithm/string/find_iterator.hpp> +#include <boost/algorithm/string/finder.hpp> +//#include <boost/lambda/lambda.hpp> +//#include <boost/lambda/bind.hpp> +// other Linden headers +#include "../test/lltut.h" +#include "../test/manageapr.h" +#include "../test/namedtempfile.h" +#include "../test/catch_and_store_what_in.h" +#include "stringize.h" +#include "llsdutil.h" +#include "llevents.h" +#include "wrapllerrs.h" + +#if defined(LL_WINDOWS) +#define sleep(secs) _sleep((secs) * 1000) +#define EOL "\r\n" +#else +#define EOL "\n" +#include <sys/wait.h> +#endif + +//namespace lambda = boost::lambda; + +// static instance of this manages APR init/cleanup +static ManageAPR manager; + +/***************************************************************************** +* Helpers +*****************************************************************************/ + +#define ensure_equals_(left, right) \ + ensure_equals(STRINGIZE(#left << " != " << #right), (left), (right)) + +#define aprchk(expr) aprchk_(#expr, (expr)) +static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS) +{ + tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << manager.strerror(rv)), + rv, expected); +} + +/** + * Read specified file using std::getline(). It is assumed to be an error if + * the file is empty: don't use this function if that's an acceptable case. + * Last line will not end with '\n'; this is to facilitate the usual case of + * string compares with a single line of output. + * @param pathname The file to read. + * @param desc Optional description of the file for error message; + * defaults to "in <pathname>" + */ +static std::string readfile(const std::string& pathname, const std::string& desc="") +{ + std::string use_desc(desc); + if (use_desc.empty()) + { + use_desc = STRINGIZE("in " << pathname); + } + std::ifstream inf(pathname.c_str()); + std::string output; + tut::ensure(STRINGIZE("No output " << use_desc), std::getline(inf, output)); + std::string more; + while (std::getline(inf, more)) + { + output += '\n' + more; + } + return output; +} + +/// Looping on LLProcess::isRunning() must now be accompanied by pumping +/// "mainloop" -- otherwise the status won't update and you get an infinite +/// loop. +void yield(int seconds=1) +{ + // This function simulates waiting for another viewer frame + sleep(seconds); + LLEventPumps::instance().obtain("mainloop").post(LLSD()); +} + +void waitfor(LLProcess& proc, int timeout=60) +{ + int i = 0; + for ( ; i < timeout && proc.isRunning(); ++i) + { + yield(); + } + tut::ensure(STRINGIZE("process took longer than " << timeout << " seconds to terminate"), + i < timeout); +} + +void waitfor(LLProcess::handle h, const std::string& desc, int timeout=60) +{ + int i = 0; + for ( ; i < timeout && LLProcess::isRunning(h, desc); ++i) + { + yield(); + } + tut::ensure(STRINGIZE("process took longer than " << timeout << " seconds to terminate"), + i < timeout); +} + +/** + * Construct an LLProcess to run a Python script. + */ +struct PythonProcessLauncher +{ + /** + * @param desc Arbitrary description for error messages + * @param script Python script, any form acceptable to NamedTempFile, + * typically either a std::string or an expression of the form + * (lambda::_1 << "script content with " << variable_data) + */ + template <typename CONTENT> + PythonProcessLauncher(const std::string& desc, const CONTENT& script): + mDesc(desc), + mScript("py", script) + { + const char* PYTHON(getenv("PYTHON")); + tut::ensure("Set $PYTHON to the Python interpreter", PYTHON); + + mParams.desc = desc + " script"; + mParams.executable = PYTHON; + mParams.args.add(mScript.getName()); + } + + /// Launch Python script; verify that it launched + void launch() + { + mPy = LLProcess::create(mParams); + tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), mPy); + } + + /// Run Python script and wait for it to complete. + void run() + { + launch(); + // One of the irritating things about LLProcess is that + // there's no API to wait for the child to terminate -- but given + // its use in our graphics-intensive interactive viewer, it's + // understandable. + waitfor(*mPy); + } + + /** + * Run a Python script using LLProcess, expecting that it will + * write to the file passed as its sys.argv[1]. Retrieve that output. + * + * Until January 2012, LLProcess provided distressingly few + * mechanisms for a child process to communicate back to its caller -- + * not even its return code. We've introduced a convention by which we + * create an empty temp file, pass the name of that file to our child + * as sys.argv[1] and expect the script to write its output to that + * file. This function implements the C++ (parent process) side of + * that convention. + */ + std::string run_read() + { + NamedTempFile out("out", ""); // placeholder + // pass name of this temporary file to the script + mParams.args.add(out.getName()); + run(); + // assuming the script wrote to that file, read it + return readfile(out.getName(), STRINGIZE("from " << mDesc << " script")); + } + + LLProcess::Params mParams; + LLProcessPtr mPy; + std::string mDesc; + NamedTempFile mScript; +}; + +/// convenience function for PythonProcessLauncher::run() +template <typename CONTENT> +static void python(const std::string& desc, const CONTENT& script) +{ + PythonProcessLauncher py(desc, script); + py.run(); +} + +/// convenience function for PythonProcessLauncher::run_read() +template <typename CONTENT> +static std::string python_out(const std::string& desc, const CONTENT& script) +{ + PythonProcessLauncher py(desc, script); + return py.run_read(); +} + +/// Create a temporary directory and clean it up later. +class NamedTempDir: public boost::noncopyable +{ +public: + // Use python() function to create a temp directory: I've found + // nothing in either Boost.Filesystem or APR quite like Python's + // tempfile.mkdtemp(). + // Special extra bonus: on Mac, mkdtemp() reports a pathname + // starting with /var/folders/something, whereas that's really a + // symlink to /private/var/folders/something. Have to use + // realpath() to compare properly. + NamedTempDir(): + mPath(python_out("mkdtemp()", + "from __future__ import with_statement\n" + "import os.path, sys, tempfile\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write(os.path.normcase(os.path.normpath(os.path.realpath(tempfile.mkdtemp()))))\n")) + {} + + ~NamedTempDir() + { + aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp)); + } + + std::string getName() const { return mPath; } + +private: + std::string mPath; +}; + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llprocess_data + { + LLAPRPool pool; + }; + typedef test_group<llprocess_data> llprocess_group; + typedef llprocess_group::object object; + llprocess_group llprocessgrp("llprocess"); + + struct Item + { + Item(): tries(0) {} + unsigned tries; + std::string which; + std::string what; + }; + +/*==========================================================================*| +#define tabent(symbol) { symbol, #symbol } + static struct ReasonCode + { + int code; + const char* name; + } reasons[] = + { + tabent(APR_OC_REASON_DEATH), + tabent(APR_OC_REASON_UNWRITABLE), + tabent(APR_OC_REASON_RESTART), + tabent(APR_OC_REASON_UNREGISTER), + tabent(APR_OC_REASON_LOST), + tabent(APR_OC_REASON_RUNNING) + }; +#undef tabent +|*==========================================================================*/ + + struct WaitInfo + { + WaitInfo(apr_proc_t* child_): + child(child_), + rv(-1), // we haven't yet called apr_proc_wait() + rc(0), + why(apr_exit_why_e(0)) + {} + apr_proc_t* child; // which subprocess + apr_status_t rv; // return from apr_proc_wait() + int rc; // child's exit code + apr_exit_why_e why; // APR_PROC_EXIT, APR_PROC_SIGNAL, APR_PROC_SIGNAL_CORE + }; + + void child_status_callback(int reason, void* data, int status) + { +/*==========================================================================*| + std::string reason_str; + BOOST_FOREACH(const ReasonCode& rcp, reasons) + { + if (reason == rcp.code) + { + reason_str = rcp.name; + break; + } + } + if (reason_str.empty()) + { + reason_str = STRINGIZE("unknown reason " << reason); + } + std::cout << "child_status_callback(" << reason_str << ")\n"; +|*==========================================================================*/ + + if (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST) + { + // Somewhat oddly, APR requires that you explicitly unregister + // even when it already knows the child has terminated. + apr_proc_other_child_unregister(data); + + WaitInfo* wi(static_cast<WaitInfo*>(data)); + // It's just wrong to call apr_proc_wait() here. The only way APR + // knows to call us with APR_OC_REASON_DEATH is that it's already + // reaped this child process, so calling wait() will only produce + // "huh?" from the OS. We must rely on the status param passed in, + // which unfortunately comes straight from the OS wait() call. +// wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT); + wi->rv = APR_CHILD_DONE; // fake apr_proc_wait() results +#if defined(LL_WINDOWS) + wi->why = APR_PROC_EXIT; + wi->rc = status; // no encoding on Windows (no signals) +#else // Posix + if (WIFEXITED(status)) + { + wi->why = APR_PROC_EXIT; + wi->rc = WEXITSTATUS(status); + } + else if (WIFSIGNALED(status)) + { + wi->why = APR_PROC_SIGNAL; + wi->rc = WTERMSIG(status); + } + else // uh, shouldn't happen? + { + wi->why = APR_PROC_EXIT; + wi->rc = status; // someone else will have to decode + } +#endif // Posix + } + } + + template<> template<> + void object::test<1>() + { + set_test_name("raw APR nonblocking I/O"); + + // Create a script file in a temporary place. + NamedTempFile script("py", + "import sys" EOL + "import time" EOL + EOL + "time.sleep(2)" EOL + "print >>sys.stdout, 'stdout after wait'" EOL + "sys.stdout.flush()" EOL + "time.sleep(2)" EOL + "print >>sys.stderr, 'stderr after wait'" EOL + "sys.stderr.flush()" EOL + ); + + // Arrange to track the history of our interaction with child: what we + // fetched, which pipe it came from, how many tries it took before we + // got it. + std::vector<Item> history; + history.push_back(Item()); + + // Run the child process. + apr_procattr_t *procattr = NULL; + aprchk(apr_procattr_create(&procattr, pool.getAPRPool())); + aprchk(apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK)); + aprchk(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH)); + + std::vector<const char*> argv; + apr_proc_t child; + argv.push_back("python"); + // Have to have a named copy of this std::string so its c_str() value + // will persist. + std::string scriptname(script.getName()); + argv.push_back(scriptname.c_str()); + argv.push_back(NULL); + + aprchk(apr_proc_create(&child, argv[0], + &argv[0], + NULL, // if we wanted to pass explicit environment + procattr, + pool.getAPRPool())); + + // We do not want this child process to outlive our APR pool. On + // destruction of the pool, forcibly kill the process. Tell APR to try + // SIGTERM and wait 3 seconds. If that didn't work, use SIGKILL. + apr_pool_note_subprocess(pool.getAPRPool(), &child, APR_KILL_AFTER_TIMEOUT); + + // arrange to call child_status_callback() + WaitInfo wi(&child); + apr_proc_other_child_register(&child, child_status_callback, &wi, child.in, pool.getAPRPool()); + + // TODO: + // Stuff child.in until it (would) block to verify EWOULDBLOCK/EAGAIN. + // Have child script clear it later, then write one more line to prove + // that it gets through. + + // Monitor two different output pipes. Because one will be closed + // before the other, keep them in a list so we can drop whichever of + // them is closed first. + typedef std::pair<std::string, apr_file_t*> DescFile; + typedef std::list<DescFile> DescFileList; + DescFileList outfiles; + outfiles.push_back(DescFile("out", child.out)); + outfiles.push_back(DescFile("err", child.err)); + + while (! outfiles.empty()) + { + // This peculiar for loop is designed to let us erase(dfli). With + // a list, that invalidates only dfli itself -- but even so, we + // lose the ability to increment it for the next item. So at the + // top of every loop, while dfli is still valid, increment + // dflnext. Then before the next iteration, set dfli to dflnext. + for (DescFileList::iterator + dfli(outfiles.begin()), dflnext(outfiles.begin()), dflend(outfiles.end()); + dfli != dflend; dfli = dflnext) + { + // Only valid to increment dflnext once we're sure it's not + // already at dflend. + ++dflnext; + + char buf[4096]; + + apr_status_t rv = apr_file_gets(buf, sizeof(buf), dfli->second); + if (APR_STATUS_IS_EOF(rv)) + { +// std::cout << "(EOF on " << dfli->first << ")\n"; +// history.back().which = dfli->first; +// history.back().what = "*eof*"; +// history.push_back(Item()); + outfiles.erase(dfli); + continue; + } + if (rv == EWOULDBLOCK || rv == EAGAIN) + { +// std::cout << "(waiting; apr_file_gets(" << dfli->first << ") => " << rv << ": " << manager.strerror(rv) << ")\n"; + ++history.back().tries; + continue; + } + aprchk_("apr_file_gets(buf, sizeof(buf), dfli->second)", rv); + // Is it even possible to get APR_SUCCESS but read 0 bytes? + // Hope not, but defend against that anyway. + if (buf[0]) + { +// std::cout << dfli->first << ": " << buf; + history.back().which = dfli->first; + history.back().what.append(buf); + if (buf[strlen(buf) - 1] == '\n') + history.push_back(Item()); + else + { + // Just for pretty output... if we only read a partial + // line, terminate it. +// std::cout << "...\n"; + } + } + } + // Do this once per tick, as we expect the viewer will + apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING); + sleep(1); + } + apr_file_close(child.in); + apr_file_close(child.out); + apr_file_close(child.err); + + // Okay, we've broken the loop because our pipes are all closed. If we + // haven't yet called wait, give the callback one more chance. This + // models the fact that unlike this small test program, the viewer + // will still be running. + if (wi.rv == -1) + { + std::cout << "last gasp apr_proc_other_child_refresh_all()\n"; + apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING); + } + + if (wi.rv == -1) + { + std::cout << "child_status_callback(APR_OC_REASON_DEATH) wasn't called" << std::endl; + wi.rv = apr_proc_wait(wi.child, &wi.rc, &wi.why, APR_NOWAIT); + } +// std::cout << "child done: rv = " << rv << " (" << manager.strerror(rv) << "), why = " << why << ", rc = " << rc << '\n'; + aprchk_("apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT)", wi.rv, APR_CHILD_DONE); + ensure_equals_(wi.why, APR_PROC_EXIT); + ensure_equals_(wi.rc, 0); + + // Beyond merely executing all the above successfully, verify that we + // obtained expected output -- and that we duly got control while + // waiting, proving the non-blocking nature of these pipes. + try + { + unsigned i = 0; + ensure("blocking I/O on child pipe (0)", history[i].tries); + ensure_equals_(history[i].which, "out"); + ensure_equals_(history[i].what, "stdout after wait" EOL); +// ++i; +// ensure_equals_(history[i].which, "out"); +// ensure_equals_(history[i].what, "*eof*"); + ++i; + ensure("blocking I/O on child pipe (1)", history[i].tries); + ensure_equals_(history[i].which, "err"); + ensure_equals_(history[i].what, "stderr after wait" EOL); +// ++i; +// ensure_equals_(history[i].which, "err"); +// ensure_equals_(history[i].what, "*eof*"); + } + catch (const failure&) + { + std::cout << "History:\n"; + BOOST_FOREACH(const Item& item, history) + { + std::string what(item.what); + if ((! what.empty()) && what[what.length() - 1] == '\n') + { + what.erase(what.length() - 1); + if ((! what.empty()) && what[what.length() - 1] == '\r') + { + what.erase(what.length() - 1); + what.append("\\r"); + } + what.append("\\n"); + } + std::cout << " " << item.which << ": '" << what << "' (" + << item.tries << " tries)\n"; + } + std::cout << std::flush; + // re-raise same error; just want to enrich the output + throw; + } + } + + template<> template<> + void object::test<2>() + { + set_test_name("setWorkingDirectory()"); + // We want to test setWorkingDirectory(). But what directory is + // guaranteed to exist on every machine, under every OS? Have to + // create one. Naturally, ensure we clean it up when done. + NamedTempDir tempdir; + PythonProcessLauncher py(get_test_name(), + "from __future__ import with_statement\n" + "import os, sys\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write(os.path.normcase(os.path.normpath(os.getcwd())))\n"); + // Before running, call setWorkingDirectory() + py.mParams.cwd = tempdir.getName(); + ensure_equals("os.getcwd()", py.run_read(), tempdir.getName()); + } + + template<> template<> + void object::test<3>() + { + set_test_name("arguments"); + PythonProcessLauncher py(get_test_name(), + "from __future__ import with_statement\n" + "import sys\n" + // note nonstandard output-file arg! + "with open(sys.argv[3], 'w') as f:\n" + " for arg in sys.argv[1:]:\n" + " print >>f, arg\n"); + // We expect that PythonProcessLauncher has already appended + // its own NamedTempFile to mParams.args (sys.argv[0]). + py.mParams.args.add("first arg"); // sys.argv[1] + py.mParams.args.add("second arg"); // sys.argv[2] + // run_read() appends() one more argument, hence [3] + std::string output(py.run_read()); + boost::split_iterator<std::string::const_iterator> + li(output, boost::first_finder("\n")), lend; + ensure("didn't get first arg", li != lend); + std::string arg(li->begin(), li->end()); + ensure_equals(arg, "first arg"); + ++li; + ensure("didn't get second arg", li != lend); + arg.assign(li->begin(), li->end()); + ensure_equals(arg, "second arg"); + ++li; + ensure("didn't get output filename?!", li != lend); + arg.assign(li->begin(), li->end()); + ensure("output filename empty?!", ! arg.empty()); + ++li; + ensure("too many args", li == lend); + } + + template<> template<> + void object::test<4>() + { + set_test_name("exit(0)"); + PythonProcessLauncher py(get_test_name(), + "import sys\n" + "sys.exit(0)\n"); + py.run(); + ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED); + ensure_equals("Status.mData", py.mPy->getStatus().mData, 0); + } + + template<> template<> + void object::test<5>() + { + set_test_name("exit(2)"); + PythonProcessLauncher py(get_test_name(), + "import sys\n" + "sys.exit(2)\n"); + py.run(); + ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED); + ensure_equals("Status.mData", py.mPy->getStatus().mData, 2); + } + + template<> template<> + void object::test<6>() + { + set_test_name("syntax_error:"); + PythonProcessLauncher py(get_test_name(), + "syntax_error:\n"); + py.mParams.files.add(LLProcess::FileParam()); // inherit stdin + py.mParams.files.add(LLProcess::FileParam()); // inherit stdout + py.mParams.files.add(LLProcess::FileParam().type("pipe")); // pipe for stderr + py.run(); + ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED); + ensure_equals("Status.mData", py.mPy->getStatus().mData, 1); + std::istream& rpipe(py.mPy->getReadPipe(LLProcess::STDERR).get_istream()); + std::vector<char> buffer(4096); + rpipe.read(&buffer[0], buffer.size()); + std::streamsize got(rpipe.gcount()); + ensure("Nothing read from stderr pipe", got); + std::string data(&buffer[0], got); + ensure("Didn't find 'SyntaxError:'", data.find("\nSyntaxError:") != std::string::npos); + } + + template<> template<> + void object::test<7>() + { + set_test_name("explicit kill()"); + PythonProcessLauncher py(get_test_name(), + "from __future__ import with_statement\n" + "import sys, time\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write('ok')\n" + "# now sleep; expect caller to kill\n" + "time.sleep(120)\n" + "# if caller hasn't managed to kill by now, bad\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write('bad')\n"); + NamedTempFile out("out", "not started"); + py.mParams.args.add(out.getName()); + py.launch(); + // Wait for the script to wake up and do its first write + int i = 0, timeout = 60; + for ( ; i < timeout; ++i) + { + yield(); + if (readfile(out.getName(), "from kill() script") == "ok") + break; + } + // If we broke this loop because of the counter, something's wrong + ensure("script never started", i < timeout); + // script has performed its first write and should now be sleeping. + py.mPy->kill(); + // wait for the script to terminate... one way or another. + waitfor(*py.mPy); +#if LL_WINDOWS + ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED); + ensure_equals("Status.mData", py.mPy->getStatus().mData, -1); +#else + ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::KILLED); + ensure_equals("Status.mData", py.mPy->getStatus().mData, SIGTERM); +#endif + // If kill() failed, the script would have woken up on its own and + // overwritten the file with 'bad'. But if kill() succeeded, it should + // not have had that chance. + ensure_equals(get_test_name() + " script output", readfile(out.getName()), "ok"); + } + + template<> template<> + void object::test<8>() + { + set_test_name("implicit kill()"); + NamedTempFile out("out", "not started"); + LLProcess::handle phandle(0); + { + PythonProcessLauncher py(get_test_name(), + "from __future__ import with_statement\n" + "import sys, time\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write('ok')\n" + "# now sleep; expect caller to kill\n" + "time.sleep(120)\n" + "# if caller hasn't managed to kill by now, bad\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write('bad')\n"); + py.mParams.args.add(out.getName()); + py.launch(); + // Capture handle for later + phandle = py.mPy->getProcessHandle(); + // Wait for the script to wake up and do its first write + int i = 0, timeout = 60; + for ( ; i < timeout; ++i) + { + yield(); + if (readfile(out.getName(), "from kill() script") == "ok") + break; + } + // If we broke this loop because of the counter, something's wrong + ensure("script never started", i < timeout); + // Script has performed its first write and should now be sleeping. + // Destroy the LLProcess, which should kill the child. + } + // wait for the script to terminate... one way or another. + waitfor(phandle, "kill() script"); + // If kill() failed, the script would have woken up on its own and + // overwritten the file with 'bad'. But if kill() succeeded, it should + // not have had that chance. + ensure_equals(get_test_name() + " script output", readfile(out.getName()), "ok"); + } + + template<> template<> + void object::test<9>() + { + set_test_name("autokill=false"); + NamedTempFile from("from", "not started"); + NamedTempFile to("to", ""); + LLProcess::handle phandle(0); + { + PythonProcessLauncher py(get_test_name(), + "from __future__ import with_statement\n" + "import sys, time\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write('ok')\n" + "# wait for 'go' from test program\n" + "for i in xrange(60):\n" + " time.sleep(1)\n" + " with open(sys.argv[2]) as f:\n" + " go = f.read()\n" + " if go == 'go':\n" + " break\n" + "else:\n" + " with open(sys.argv[1], 'w') as f:\n" + " f.write('never saw go')\n" + " sys.exit(1)\n" + "# okay, saw 'go', write 'ack'\n" + "with open(sys.argv[1], 'w') as f:\n" + " f.write('ack')\n"); + py.mParams.args.add(from.getName()); + py.mParams.args.add(to.getName()); + py.mParams.autokill = false; + py.launch(); + // Capture handle for later + phandle = py.mPy->getProcessHandle(); + // Wait for the script to wake up and do its first write + int i = 0, timeout = 60; + for ( ; i < timeout; ++i) + { + yield(); + if (readfile(from.getName(), "from autokill script") == "ok") + break; + } + // If we broke this loop because of the counter, something's wrong + ensure("script never started", i < timeout); + // Now destroy the LLProcess, which should NOT kill the child! + } + // If the destructor killed the child anyway, give it time to die + yield(2); + // How do we know it's not terminated? By making it respond to + // a specific stimulus in a specific way. + { + std::ofstream outf(to.getName().c_str()); + outf << "go"; + } // flush and close. + // now wait for the script to terminate... one way or another. + waitfor(phandle, "autokill script"); + // If the LLProcess destructor implicitly called kill(), the + // script could not have written 'ack' as we expect. + ensure_equals(get_test_name() + " script output", readfile(from.getName()), "ack"); + } + + template<> template<> + void object::test<10>() + { + set_test_name("'bogus' test"); + CaptureLog recorder; + PythonProcessLauncher py(get_test_name(), + "print 'Hello world'\n"); + py.mParams.files.add(LLProcess::FileParam("bogus")); + py.mPy = LLProcess::create(py.mParams); + ensure("should have rejected 'bogus'", ! py.mPy); + std::string message(recorder.messageWith("bogus")); + ensure_contains("did not name 'stdin'", message, "stdin"); + } + + template<> template<> + void object::test<11>() + { + set_test_name("'file' test"); + // Replace this test with one or more real 'file' tests when we + // implement 'file' support + PythonProcessLauncher py(get_test_name(), + "print 'Hello world'\n"); + py.mParams.files.add(LLProcess::FileParam()); + py.mParams.files.add(LLProcess::FileParam("file")); + py.mPy = LLProcess::create(py.mParams); + ensure("should have rejected 'file'", ! py.mPy); + } + + template<> template<> + void object::test<12>() + { + set_test_name("'tpipe' test"); + // Replace this test with one or more real 'tpipe' tests when we + // implement 'tpipe' support + CaptureLog recorder; + PythonProcessLauncher py(get_test_name(), + "print 'Hello world'\n"); + py.mParams.files.add(LLProcess::FileParam()); + py.mParams.files.add(LLProcess::FileParam("tpipe")); + py.mPy = LLProcess::create(py.mParams); + ensure("should have rejected 'tpipe'", ! py.mPy); + std::string message(recorder.messageWith("tpipe")); + ensure_contains("did not name 'stdout'", message, "stdout"); + } + + template<> template<> + void object::test<13>() + { + set_test_name("'npipe' test"); + // Replace this test with one or more real 'npipe' tests when we + // implement 'npipe' support + CaptureLog recorder; + PythonProcessLauncher py(get_test_name(), + "print 'Hello world'\n"); + py.mParams.files.add(LLProcess::FileParam()); + py.mParams.files.add(LLProcess::FileParam()); + py.mParams.files.add(LLProcess::FileParam("npipe")); + py.mPy = LLProcess::create(py.mParams); + ensure("should have rejected 'npipe'", ! py.mPy); + std::string message(recorder.messageWith("npipe")); + ensure_contains("did not name 'stderr'", message, "stderr"); + } + + template<> template<> + void object::test<14>() + { + set_test_name("internal pipe name warning"); + CaptureLog recorder; + PythonProcessLauncher py(get_test_name(), + "import sys\n" + "sys.exit(7)\n"); + py.mParams.files.add(LLProcess::FileParam("pipe", "somename")); + py.run(); // verify that it did launch anyway + ensure_equals("Status.mState", py.mPy->getStatus().mState, LLProcess::EXITED); + ensure_equals("Status.mData", py.mPy->getStatus().mData, 7); + std::string message(recorder.messageWith("not yet supported")); + ensure_contains("log message did not mention internal pipe name", + message, "somename"); + } + + /*-------------- support for "get*Pipe() validation" test --------------*/ +#define TEST_getPipe(PROCESS, GETPIPE, GETOPTPIPE, VALID, NOPIPE, BADPIPE) \ + do \ + { \ + std::string threw; \ + /* Both the following calls should work. */ \ + (PROCESS).GETPIPE(VALID); \ + ensure(#GETOPTPIPE "(" #VALID ") failed", (PROCESS).GETOPTPIPE(VALID)); \ + /* pass obviously bogus PIPESLOT */ \ + CATCH_IN(threw, LLProcess::NoPipe, (PROCESS).GETPIPE(LLProcess::FILESLOT(4))); \ + ensure_contains("didn't reject bad slot", threw, "no slot"); \ + ensure_contains("didn't mention bad slot num", threw, "4"); \ + EXPECT_FAIL_WITH_LOG(threw, (PROCESS).GETOPTPIPE(LLProcess::FILESLOT(4))); \ + /* pass NOPIPE */ \ + CATCH_IN(threw, LLProcess::NoPipe, (PROCESS).GETPIPE(NOPIPE)); \ + ensure_contains("didn't reject non-pipe", threw, "not a monitored"); \ + EXPECT_FAIL_WITH_LOG(threw, (PROCESS).GETOPTPIPE(NOPIPE)); \ + /* pass BADPIPE: FILESLOT isn't empty but wrong direction */ \ + CATCH_IN(threw, LLProcess::NoPipe, (PROCESS).GETPIPE(BADPIPE)); \ + /* sneaky: GETPIPE is getReadPipe or getWritePipe */ \ + /* so skip "get" to obtain ReadPipe or WritePipe :-P */ \ + ensure_contains("didn't reject wrong pipe", threw, (#GETPIPE)+3); \ + EXPECT_FAIL_WITH_LOG(threw, (PROCESS).GETOPTPIPE(BADPIPE)); \ + } while (0) + +/// For expecting exceptions. Execute CODE, catch EXCEPTION, store its what() +/// in std::string THREW, ensure it's not empty (i.e. EXCEPTION did happen). +#define CATCH_IN(THREW, EXCEPTION, CODE) \ + do \ + { \ + (THREW).clear(); \ + try \ + { \ + CODE; \ + } \ + CATCH_AND_STORE_WHAT_IN(THREW, EXCEPTION) \ + ensure("failed to throw " #EXCEPTION ": " #CODE, ! (THREW).empty()); \ + } while (0) + +#define EXPECT_FAIL_WITH_LOG(EXPECT, CODE) \ + do \ + { \ + CaptureLog recorder; \ + ensure(#CODE " succeeded", ! (CODE)); \ + recorder.messageWith(EXPECT); \ + } while (0) + + template<> template<> + void object::test<15>() + { + set_test_name("get*Pipe() validation"); + PythonProcessLauncher py(get_test_name(), + "print 'this output is expected'\n"); + py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stdin + py.mParams.files.add(LLProcess::FileParam()); // inherit stdout + py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stderr + py.run(); + TEST_getPipe(*py.mPy, getWritePipe, getOptWritePipe, + LLProcess::STDIN, // VALID + LLProcess::STDOUT, // NOPIPE + LLProcess::STDERR); // BADPIPE + TEST_getPipe(*py.mPy, getReadPipe, getOptReadPipe, + LLProcess::STDERR, // VALID + LLProcess::STDOUT, // NOPIPE + LLProcess::STDIN); // BADPIPE + } + + template<> template<> + void object::test<16>() + { + set_test_name("talk to stdin/stdout"); + PythonProcessLauncher py(get_test_name(), + "import sys, time\n" + "print 'ok'\n" + "sys.stdout.flush()\n" + "# wait for 'go' from test program\n" + "go = sys.stdin.readline()\n" + "if go != 'go\\n':\n" + " sys.exit('expected \"go\", saw %r' % go)\n" + "print 'ack'\n"); + py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin + py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout + py.launch(); + LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT)); + int i, timeout = 60; + for (i = 0; i < timeout && py.mPy->isRunning() && childout.size() < 3; ++i) + { + yield(); + } + ensure("script never started", i < timeout); + ensure_equals("bad wakeup from stdin/stdout script", + childout.getline(), "ok"); + // important to get the implicit flush from std::endl + py.mPy->getWritePipe().get_ostream() << "go" << std::endl; + for (i = 0; i < timeout && py.mPy->isRunning() && ! childout.contains("\n"); ++i) + { + yield(); + } + ensure("script never replied", childout.contains("\n")); + ensure_equals("child didn't ack", childout.getline(), "ack"); + ensure_equals("bad child termination", py.mPy->getStatus().mState, LLProcess::EXITED); + ensure_equals("bad child exit code", py.mPy->getStatus().mData, 0); + } + + struct EventListener: public boost::noncopyable + { + EventListener(LLEventPump& pump) + { + mConnection = + pump.listen("EventListener", boost::bind(&EventListener::tick, this, _1)); + } + + bool tick(const LLSD& data) + { + mHistory.push_back(data); + return false; + } + + std::list<LLSD> mHistory; + LLTempBoundListener mConnection; + }; + + static bool ack(std::ostream& out, const LLSD& data) + { + out << "continue" << std::endl; + return false; + } + + template<> template<> + void object::test<17>() + { + set_test_name("listen for ReadPipe events"); + PythonProcessLauncher py(get_test_name(), + "import sys\n" + "sys.stdout.write('abc')\n" + "sys.stdout.flush()\n" + "sys.stdin.readline()\n" + "sys.stdout.write('def')\n" + "sys.stdout.flush()\n" + "sys.stdin.readline()\n" + "sys.stdout.write('ghi\\n')\n" + "sys.stdout.flush()\n" + "sys.stdin.readline()\n" + "sys.stdout.write('second line\\n')\n"); + py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin + py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout + py.launch(); + std::ostream& childin(py.mPy->getWritePipe(LLProcess::STDIN).get_ostream()); + LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT)); + // lift the default limit; allow event to carry (some of) the actual data + childout.setLimit(20); + // listen for incoming data on childout + EventListener listener(childout.getPump()); + // also listen with a function that prompts the child to continue + // every time we see output + LLTempBoundListener connection( + childout.getPump().listen("ack", boost::bind(ack, boost::ref(childin), _1))); + int i, timeout = 60; + // wait through stuttering first line + for (i = 0; i < timeout && py.mPy->isRunning() && ! childout.contains("\n"); ++i) + { + yield(); + } + ensure("couldn't get first line", i < timeout); + // disconnect from listener + listener.mConnection.disconnect(); + // finish out the run + waitfor(*py.mPy); + // now verify history + std::list<LLSD>::const_iterator li(listener.mHistory.begin()), + lend(listener.mHistory.end()); + ensure("no events", li != lend); + ensure_equals("history[0]", (*li)["data"].asString(), "abc"); + ensure_equals("history[0] len", (*li)["len"].asInteger(), 3); + ++li; + ensure("only 1 event", li != lend); + ensure_equals("history[1]", (*li)["data"].asString(), "abcdef"); + ensure_equals("history[0] len", (*li)["len"].asInteger(), 6); + ++li; + ensure("only 2 events", li != lend); + ensure_equals("history[2]", (*li)["data"].asString(), "abcdefghi" EOL); + ensure_equals("history[0] len", (*li)["len"].asInteger(), 9 + sizeof(EOL) - 1); + ++li; + // We DO NOT expect a whole new event for the second line because we + // disconnected. + ensure("more than 3 events", li == lend); + } + + template<> template<> + void object::test<18>() + { + set_test_name("ReadPipe \"eof\" event"); + PythonProcessLauncher py(get_test_name(), + "print 'Hello from Python!'\n"); + py.mParams.files.add(LLProcess::FileParam()); // stdin + py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout + py.launch(); + LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT)); + EventListener listener(childout.getPump()); + waitfor(*py.mPy); + // We can't be positive there will only be a single event, if the OS + // (or any other intervening layer) does crazy buffering. What we want + // to ensure is that there was exactly ONE event with "eof" true, and + // that it was the LAST event. + std::list<LLSD>::const_reverse_iterator rli(listener.mHistory.rbegin()), + rlend(listener.mHistory.rend()); + ensure("no events", rli != rlend); + ensure("last event not \"eof\"", (*rli)["eof"].asBoolean()); + while (++rli != rlend) + { + ensure("\"eof\" event not last", ! (*rli)["eof"].asBoolean()); + } + } + + template<> template<> + void object::test<19>() + { + set_test_name("setLimit()"); + PythonProcessLauncher py(get_test_name(), + "import sys\n" + "sys.stdout.write(sys.argv[1])\n"); + std::string abc("abcdefghijklmnopqrstuvwxyz"); + py.mParams.args.add(abc); + py.mParams.files.add(LLProcess::FileParam()); // stdin + py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout + py.launch(); + LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT)); + // listen for incoming data on childout + EventListener listener(childout.getPump()); + // but set limit + childout.setLimit(10); + ensure_equals("getLimit() after setlimit(10)", childout.getLimit(), 10); + // okay, pump I/O to pick up output from child + waitfor(*py.mPy); + ensure("no events", ! listener.mHistory.empty()); + // For all we know, that data could have arrived in several different + // bursts... probably not, but anyway, only check the last one. + ensure_equals("event[\"len\"]", + listener.mHistory.back()["len"].asInteger(), abc.length()); + ensure_equals("length of setLimit(10) data", + listener.mHistory.back()["data"].asString().length(), 10); + } + + template<> template<> + void object::test<20>() + { + set_test_name("peek() ReadPipe data"); + PythonProcessLauncher py(get_test_name(), + "import sys\n" + "sys.stdout.write(sys.argv[1])\n"); + std::string abc("abcdefghijklmnopqrstuvwxyz"); + py.mParams.args.add(abc); + py.mParams.files.add(LLProcess::FileParam()); // stdin + py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout + py.launch(); + LLProcess::ReadPipe& childout(py.mPy->getReadPipe(LLProcess::STDOUT)); + // okay, pump I/O to pick up output from child + waitfor(*py.mPy); + // peek() with substr args + ensure_equals("peek()", childout.peek(), abc); + ensure_equals("peek(23)", childout.peek(23), abc.substr(23)); + ensure_equals("peek(5, 3)", childout.peek(5, 3), abc.substr(5, 3)); + ensure_equals("peek(27, 2)", childout.peek(27, 2), ""); + ensure_equals("peek(23, 5)", childout.peek(23, 5), "xyz"); + // contains() -- we don't exercise as thoroughly as find() because the + // contains() implementation is trivially (and visibly) based on find() + ensure("contains(\":\")", ! childout.contains(":")); + ensure("contains(':')", ! childout.contains(':')); + ensure("contains(\"d\")", childout.contains("d")); + ensure("contains('d')", childout.contains('d')); + ensure("contains(\"klm\")", childout.contains("klm")); + ensure("contains(\"klx\")", ! childout.contains("klx")); + // find() + ensure("find(\":\")", childout.find(":") == LLProcess::ReadPipe::npos); + ensure("find(':')", childout.find(':') == LLProcess::ReadPipe::npos); + ensure_equals("find(\"d\")", childout.find("d"), 3); + ensure_equals("find('d')", childout.find('d'), 3); + ensure_equals("find(\"d\", 3)", childout.find("d", 3), 3); + ensure_equals("find('d', 3)", childout.find('d', 3), 3); + ensure("find(\"d\", 4)", childout.find("d", 4) == LLProcess::ReadPipe::npos); + ensure("find('d', 4)", childout.find('d', 4) == LLProcess::ReadPipe::npos); + // The case of offset == end and offset > end are different. In the + // first case, we can form a valid (albeit empty) iterator range and + // search that. In the second, guard logic in the implementation must + // realize we can't form a valid iterator range. + ensure("find(\"d\", 26)", childout.find("d", 26) == LLProcess::ReadPipe::npos); + ensure("find('d', 26)", childout.find('d', 26) == LLProcess::ReadPipe::npos); + ensure("find(\"d\", 27)", childout.find("d", 27) == LLProcess::ReadPipe::npos); + ensure("find('d', 27)", childout.find('d', 27) == LLProcess::ReadPipe::npos); + ensure_equals("find(\"ghi\")", childout.find("ghi"), 6); + ensure_equals("find(\"ghi\", 6)", childout.find("ghi"), 6); + ensure("find(\"ghi\", 7)", childout.find("ghi", 7) == LLProcess::ReadPipe::npos); + ensure("find(\"ghi\", 26)", childout.find("ghi", 26) == LLProcess::ReadPipe::npos); + ensure("find(\"ghi\", 27)", childout.find("ghi", 27) == LLProcess::ReadPipe::npos); + } + + template<> template<> + void object::test<21>() + { + set_test_name("bad postend"); + std::string pumpname("postend"); + EventListener listener(LLEventPumps::instance().obtain(pumpname)); + LLProcess::Params params; + params.desc = get_test_name(); + params.postend = pumpname; + LLProcessPtr child = LLProcess::create(params); + ensure("shouldn't have launched", ! child); + ensure_equals("number of postend events", listener.mHistory.size(), 1); + LLSD postend(listener.mHistory.front()); + ensure("has id", ! postend.has("id")); + ensure_equals("desc", postend["desc"].asString(), std::string(params.desc)); + ensure_equals("state", postend["state"].asInteger(), LLProcess::UNSTARTED); + ensure("has data", ! postend.has("data")); + std::string error(postend["string"]); + // All we get from canned parameter validation is a bool, so the + // "validation failed" message we ourselves generate can't mention + // "executable" by name. Just check that it's nonempty. + //ensure_contains("error", error, "executable"); + ensure("string", ! error.empty()); + } + + template<> template<> + void object::test<22>() + { + set_test_name("good postend"); + PythonProcessLauncher py(get_test_name(), + "import sys\n" + "sys.exit(35)\n"); + std::string pumpname("postend"); + EventListener listener(LLEventPumps::instance().obtain(pumpname)); + py.mParams.postend = pumpname; + py.launch(); + LLProcess::id childid(py.mPy->getProcessID()); + // Don't use waitfor(), which calls isRunning(); instead wait for an + // event on pumpname. + int i, timeout = 60; + for (i = 0; i < timeout && listener.mHistory.empty(); ++i) + { + yield(); + } + ensure("no postend event", i < timeout); + ensure_equals("number of postend events", listener.mHistory.size(), 1); + LLSD postend(listener.mHistory.front()); + ensure_equals("id", postend["id"].asInteger(), childid); + ensure("desc empty", ! postend["desc"].asString().empty()); + ensure_equals("state", postend["state"].asInteger(), LLProcess::EXITED); + ensure_equals("data", postend["data"].asInteger(), 35); + std::string str(postend["string"]); + ensure_contains("string", str, "exited"); + ensure_contains("string", str, "35"); + } + + struct PostendListener + { + PostendListener(LLProcess::ReadPipe& rpipe, + const std::string& pumpname, + const std::string& expect): + mReadPipe(rpipe), + mExpect(expect), + mTriggered(false) + { + LLEventPumps::instance().obtain(pumpname) + .listen("PostendListener", boost::bind(&PostendListener::postend, this, _1)); + } + + bool postend(const LLSD&) + { + mTriggered = true; + ensure_equals("postend listener", mReadPipe.read(mReadPipe.size()), mExpect); + return false; + } + + LLProcess::ReadPipe& mReadPipe; + std::string mExpect; + bool mTriggered; + }; + + template<> template<> + void object::test<23>() + { + set_test_name("all data visible at postend"); + PythonProcessLauncher py(get_test_name(), + "import sys\n" + // note, no '\n' in written data + "sys.stdout.write('partial line')\n"); + std::string pumpname("postend"); + py.mParams.files.add(LLProcess::FileParam()); // stdin + py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout + py.mParams.postend = pumpname; + py.launch(); + PostendListener listener(py.mPy->getReadPipe(LLProcess::STDOUT), + pumpname, + "partial line"); + waitfor(*py.mPy); + ensure("postend never triggered", listener.mTriggered); + } +} // namespace tut diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 72322c3b72..e625545763 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -40,41 +40,15 @@ typedef U32 uint32_t; #include <fcntl.h> #include <sys/stat.h> #include <sys/wait.h> -#include "llprocesslauncher.h" +#include "llprocess.h" #endif -#include <sstream> - -/*==========================================================================*| -// Whoops, seems Linden's Boost package and the viewer are built with -// different settings of VC's /Zc:wchar_t switch! Using Boost.Filesystem -// pathname operations produces Windows link errors: -// unresolved external symbol "private: static class std::codecvt<unsigned short, -// char,int> const * & __cdecl boost::filesystem3::path::wchar_t_codecvt_facet()" -// unresolved external symbol "void __cdecl boost::filesystem3::path_traits::convert()" -// See: -// http://boost.2283326.n4.nabble.com/filesystem-v3-unicode-and-std-codecvt-linker-error-td3455549.html -// which points to: -// http://msdn.microsoft.com/en-us/library/dh8che7s%28v=VS.100%29.aspx - -// As we're not trying to preserve compatibility with old Boost.Filesystem -// code, but rather writing brand-new code, use the newest available -// Filesystem API. -#define BOOST_FILESYSTEM_VERSION 3 -#include "boost/filesystem.hpp" -#include "boost/filesystem/v3/fstream.hpp" -|*==========================================================================*/ #include "boost/range.hpp" #include "boost/foreach.hpp" #include "boost/function.hpp" #include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" namespace lambda = boost::lambda; -/*==========================================================================*| -// Aaaarrgh, Linden's Boost package doesn't even include Boost.Iostreams! -#include "boost/iostreams/stream.hpp" -#include "boost/iostreams/device/file_descriptor.hpp" -|*==========================================================================*/ #include "../llsd.h" #include "../llsdserialize.h" @@ -82,236 +56,17 @@ namespace lambda = boost::lambda; #include "../llformat.h" #include "../test/lltut.h" +#include "../test/manageapr.h" +#include "../test/namedtempfile.h" #include "stringize.h" +static ManageAPR manager; + std::vector<U8> string_to_vector(const std::string& str) { return std::vector<U8>(str.begin(), str.end()); } -#if ! LL_WINDOWS -// We want to call strerror_r(), but alarmingly, there are two different -// variants. The one that returns int always populates the passed buffer -// (except in case of error), whereas the other one always returns a valid -// char* but might or might not populate the passed buffer. How do we know -// which one we're getting? Define adapters for each and let the compiler -// select the applicable adapter. - -// strerror_r() returns char* -std::string message_from(int /*orig_errno*/, const char* /*buffer*/, const char* strerror_ret) -{ - return strerror_ret; -} - -// strerror_r() returns int -std::string message_from(int orig_errno, const char* buffer, int strerror_ret) -{ - if (strerror_ret == 0) - { - return buffer; - } - // Here strerror_r() has set errno. Since strerror_r() has already failed, - // seems like a poor bet to call it again to diagnose its own error... - int stre_errno = errno; - if (stre_errno == ERANGE) - { - return STRINGIZE("strerror_r() can't explain errno " << orig_errno - << " (buffer too small)"); - } - if (stre_errno == EINVAL) - { - return STRINGIZE("unknown errno " << orig_errno); - } - // Here we don't even understand the errno from strerror_r()! - return STRINGIZE("strerror_r() can't explain errno " << orig_errno - << " (error " << stre_errno << ')'); -} -#endif // ! LL_WINDOWS - -// boost::filesystem::temp_directory_path() isn't yet in Boost 1.45! :-( -std::string temp_directory_path() -{ -#if LL_WINDOWS - char buffer[4096]; - GetTempPathA(sizeof(buffer), buffer); - return buffer; - -#else // LL_DARWIN, LL_LINUX - static const char* vars[] = { "TMPDIR", "TMP", "TEMP", "TEMPDIR" }; - BOOST_FOREACH(const char* var, vars) - { - const char* found = getenv(var); - if (found) - return found; - } - return "/tmp"; -#endif // LL_DARWIN, LL_LINUX -} - -// Windows presents a kinda sorta compatibility layer. Code to the yucky -// Windows names because they're less likely than the Posix names to collide -// with any other names in this source. -#if LL_WINDOWS -#define _remove DeleteFileA -#else // ! LL_WINDOWS -#define _open open -#define _write write -#define _close close -#define _remove remove -#endif // ! LL_WINDOWS - -// Create a text file with specified content "somewhere in the -// filesystem," cleaning up when it goes out of scope. -class NamedTempFile -{ -public: - // Function that accepts an ostream ref and (presumably) writes stuff to - // it, e.g.: - // (lambda::_1 << "the value is " << 17 << '\n') - typedef boost::function<void(std::ostream&)> Streamer; - - NamedTempFile(const std::string& ext, const std::string& content): - mPath(temp_directory_path()) - { - createFile(ext, lambda::_1 << content); - } - - // Disambiguate when passing string literal - NamedTempFile(const std::string& ext, const char* content): - mPath(temp_directory_path()) - { - createFile(ext, lambda::_1 << content); - } - - NamedTempFile(const std::string& ext, const Streamer& func): - mPath(temp_directory_path()) - { - createFile(ext, func); - } - - ~NamedTempFile() - { - _remove(mPath.c_str()); - } - - std::string getName() const { return mPath; } - -private: - void createFile(const std::string& ext, const Streamer& func) - { - // Silly maybe, but use 'ext' as the name prefix. Strip off a leading - // '.' if present. - int pfx_offset = ((! ext.empty()) && ext[0] == '.')? 1 : 0; - -#if ! LL_WINDOWS - // Make sure mPath ends with a directory separator, if it doesn't already. - if (mPath.empty() || - ! (mPath[mPath.length() - 1] == '\\' || mPath[mPath.length() - 1] == '/')) - { - mPath.append("/"); - } - - // mkstemp() accepts and modifies a char* template string. Generate - // the template string, then copy to modifiable storage. - // mkstemp() requires its template string to end in six X's. - mPath += ext.substr(pfx_offset) + "XXXXXX"; - // Copy to vector<char> - std::vector<char> pathtemplate(mPath.begin(), mPath.end()); - // append a nul byte for classic-C semantics - pathtemplate.push_back('\0'); - // std::vector promises that a pointer to the 0th element is the same - // as a pointer to a contiguous classic-C array - int fd(mkstemp(&pathtemplate[0])); - if (fd == -1) - { - // The documented errno values (http://linux.die.net/man/3/mkstemp) - // are used in a somewhat unusual way, so provide context-specific - // errors. - if (errno == EEXIST) - { - LL_ERRS("NamedTempFile") << "mkstemp(\"" << mPath - << "\") could not create unique file " << LL_ENDL; - } - if (errno == EINVAL) - { - LL_ERRS("NamedTempFile") << "bad mkstemp() file path template '" - << mPath << "'" << LL_ENDL; - } - // Shrug, something else - int mkst_errno = errno; - char buffer[256]; - LL_ERRS("NamedTempFile") << "mkstemp(\"" << mPath << "\") failed: " - << message_from(mkst_errno, buffer, - strerror_r(mkst_errno, buffer, sizeof(buffer))) - << LL_ENDL; - } - // mkstemp() seems to have worked! Capture the modified filename. - // Avoid the nul byte we appended. - mPath.assign(pathtemplate.begin(), (pathtemplate.end()-1)); - -/*==========================================================================*| - // Define an ostream on the open fd. Tell it to close fd on destruction. - boost::iostreams::stream<boost::iostreams::file_descriptor_sink> - out(fd, boost::iostreams::close_handle); -|*==========================================================================*/ - - // Write desired content. - std::ostringstream out; - // Stream stuff to it. - func(out); - - std::string data(out.str()); - int written(_write(fd, data.c_str(), data.length())); - int closed(_close(fd)); - llassert_always(written == data.length() && closed == 0); - -#else // LL_WINDOWS - // GetTempFileName() is documented to require a MAX_PATH buffer. - char tempname[MAX_PATH]; - // Use 'ext' as filename prefix, but skip leading '.' if any. - // The 0 param is very important: requests iterating until we get a - // unique name. - if (0 == GetTempFileNameA(mPath.c_str(), ext.c_str() + pfx_offset, 0, tempname)) - { - // I always have to look up this call... :-P - LPSTR msgptr; - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - LPSTR(&msgptr), // have to cast (char**) to (char*) - 0, NULL ); - LL_ERRS("NamedTempFile") << "GetTempFileName(\"" << mPath << "\", \"" - << (ext.c_str() + pfx_offset) << "\") failed: " - << msgptr << LL_ENDL; - LocalFree(msgptr); - } - // GetTempFileName() appears to have worked! Capture the actual - // filename. - mPath = tempname; - // Open the file and stream content to it. Destructor will close. - std::ofstream out(tempname); - func(out); - -#endif // LL_WINDOWS - } - - void peep() - { - std::cout << "File '" << mPath << "' contains:\n"; - std::ifstream reader(mPath.c_str()); - std::string line; - while (std::getline(reader, line)) - std::cout << line << '\n'; - std::cout << "---\n"; - } - - std::string mPath; -}; - namespace tut { struct sd_xml_data @@ -1783,7 +1538,7 @@ namespace tut const char* PYTHON(getenv("PYTHON")); ensure("Set $PYTHON to the Python interpreter", PYTHON); - NamedTempFile scriptfile(".py", script); + NamedTempFile scriptfile("py", script); #if LL_WINDOWS std::string q("\""); @@ -1802,14 +1557,15 @@ namespace tut } #else // LL_DARWIN, LL_LINUX - LLProcessLauncher py; - py.setExecutable(PYTHON); - py.addArgument(scriptfile.getName()); - ensure_equals(STRINGIZE("Couldn't launch " << desc << " script"), py.launch(), 0); + LLProcess::Params params; + params.executable = PYTHON; + params.args.add(scriptfile.getName()); + LLProcessPtr py(LLProcess::create(params)); + ensure(STRINGIZE("Couldn't launch " << desc << " script"), py); // Implementing timeout would mean messing with alarm() and // catching SIGALRM... later maybe... int status(0); - if (waitpid(py.getProcessID(), &status, 0) == -1) + if (waitpid(py->getProcessID(), &status, 0) == -1) { int waitpid_errno(errno); ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: " @@ -1888,12 +1644,12 @@ namespace tut " else:\n" " assert False, 'Too many data items'\n"; - // Create a something.llsd file containing 'data' serialized to + // Create an llsdXXXXXX file containing 'data' serialized to // notation. It's important to separate with newlines because Python's // llsd module doesn't support parsing from a file stream, only from a // string, so we have to know how much of the file to read into a // string. - NamedTempFile file(".llsd", + NamedTempFile file("llsd", // NamedTempFile's boost::function constructor // takes a callable. To this callable it passes the // std::ostream with which it's writing the @@ -1926,7 +1682,7 @@ namespace tut // Create an empty data file. This is just a placeholder for our // script to write into. Create it to establish a unique name that // we know. - NamedTempFile file(".llsd", ""); + NamedTempFile file("llsd", ""); python("write Python notation", lambda::_1 << diff --git a/indra/llcommon/tests/llstreamqueue_test.cpp b/indra/llcommon/tests/llstreamqueue_test.cpp new file mode 100644 index 0000000000..050ad5c5bf --- /dev/null +++ b/indra/llcommon/tests/llstreamqueue_test.cpp @@ -0,0 +1,197 @@ +/** + * @file llstreamqueue_test.cpp + * @author Nat Goodspeed + * @date 2012-01-05 + * @brief Test for llstreamqueue. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llstreamqueue.h" +// STL headers +#include <vector> +// std headers +// external library headers +#include <boost/foreach.hpp> +// other Linden headers +#include "../test/lltut.h" +#include "stringize.h" + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llstreamqueue_data + { + llstreamqueue_data(): + // we want a buffer with actual bytes in it, not an empty vector + buffer(10) + {} + // As LLStreamQueue is merely a typedef for + // LLGenericStreamQueue<char>, and no logic in LLGenericStreamQueue is + // specific to the <char> instantiation, we're comfortable for now + // testing only the narrow-char version. + LLStreamQueue strq; + // buffer for use in multiple tests + std::vector<char> buffer; + }; + typedef test_group<llstreamqueue_data> llstreamqueue_group; + typedef llstreamqueue_group::object object; + llstreamqueue_group llstreamqueuegrp("llstreamqueue"); + + template<> template<> + void object::test<1>() + { + set_test_name("empty LLStreamQueue"); + ensure_equals("brand-new LLStreamQueue isn't empty", + strq.size(), 0); + ensure_equals("brand-new LLStreamQueue returns data", + strq.asSource().read(&buffer[0], buffer.size()), 0); + strq.asSink().close(); + ensure_equals("closed empty LLStreamQueue not at EOF", + strq.asSource().read(&buffer[0], buffer.size()), -1); + } + + template<> template<> + void object::test<2>() + { + set_test_name("one internal block, one buffer"); + LLStreamQueue::Sink sink(strq.asSink()); + ensure_equals("write(\"\")", sink.write("", 0), 0); + ensure_equals("0 write should leave LLStreamQueue empty (size())", + strq.size(), 0); + ensure_equals("0 write should leave LLStreamQueue empty (peek())", + strq.peek(&buffer[0], buffer.size()), 0); + // The meaning of "atomic" is that it must be smaller than our buffer. + std::string atomic("atomic"); + ensure("test data exceeds buffer", atomic.length() < buffer.size()); + ensure_equals(STRINGIZE("write(\"" << atomic << "\")"), + sink.write(&atomic[0], atomic.length()), atomic.length()); + ensure_equals("size() after write()", strq.size(), atomic.length()); + size_t peeklen(strq.peek(&buffer[0], buffer.size())); + ensure_equals(STRINGIZE("peek(\"" << atomic << "\")"), + peeklen, atomic.length()); + ensure_equals(STRINGIZE("peek(\"" << atomic << "\") result"), + std::string(buffer.begin(), buffer.begin() + peeklen), atomic); + ensure_equals("size() after peek()", strq.size(), atomic.length()); + // peek() should not consume. Use a different buffer to prove it isn't + // just leftover data from the first peek(). + std::vector<char> again(buffer.size()); + peeklen = size_t(strq.peek(&again[0], again.size())); + ensure_equals(STRINGIZE("peek(\"" << atomic << "\") again"), + peeklen, atomic.length()); + ensure_equals(STRINGIZE("peek(\"" << atomic << "\") again result"), + std::string(again.begin(), again.begin() + peeklen), atomic); + // now consume. + std::vector<char> third(buffer.size()); + size_t readlen(strq.read(&third[0], third.size())); + ensure_equals(STRINGIZE("read(\"" << atomic << "\")"), + readlen, atomic.length()); + ensure_equals(STRINGIZE("read(\"" << atomic << "\") result"), + std::string(third.begin(), third.begin() + readlen), atomic); + ensure_equals("peek() after read()", strq.peek(&buffer[0], buffer.size()), 0); + ensure_equals("size() after read()", strq.size(), 0); + } + + template<> template<> + void object::test<3>() + { + set_test_name("basic skip()"); + std::string lovecraft("lovecraft"); + ensure("test data exceeds buffer", lovecraft.length() < buffer.size()); + ensure_equals(STRINGIZE("write(\"" << lovecraft << "\")"), + strq.write(&lovecraft[0], lovecraft.length()), lovecraft.length()); + size_t peeklen(strq.peek(&buffer[0], buffer.size())); + ensure_equals(STRINGIZE("peek(\"" << lovecraft << "\")"), + peeklen, lovecraft.length()); + ensure_equals(STRINGIZE("peek(\"" << lovecraft << "\") result"), + std::string(buffer.begin(), buffer.begin() + peeklen), lovecraft); + std::streamsize skip1(4); + ensure_equals(STRINGIZE("skip(" << skip1 << ")"), strq.skip(skip1), skip1); + ensure_equals("size() after skip()", strq.size(), lovecraft.length() - skip1); + size_t readlen(strq.read(&buffer[0], buffer.size())); + ensure_equals(STRINGIZE("read(\"" << lovecraft.substr(skip1) << "\")"), + readlen, lovecraft.length() - skip1); + ensure_equals(STRINGIZE("read(\"" << lovecraft.substr(skip1) << "\") result"), + std::string(buffer.begin(), buffer.begin() + readlen), + lovecraft.substr(skip1)); + ensure_equals("unconsumed", strq.read(&buffer[0], buffer.size()), 0); + } + + template<> template<> + void object::test<4>() + { + set_test_name("skip() multiple blocks"); + std::string blocks[] = { "books of ", "H.P. ", "Lovecraft" }; + std::streamsize total(blocks[0].length() + blocks[1].length() + blocks[2].length()); + std::streamsize leave(5); // len("craft") above + std::streamsize skip(total - leave); + std::streamsize written(0); + BOOST_FOREACH(const std::string& block, blocks) + { + written += strq.write(&block[0], block.length()); + ensure_equals("size() after write()", strq.size(), written); + } + std::streamsize skiplen(strq.skip(skip)); + ensure_equals(STRINGIZE("skip(" << skip << ")"), skiplen, skip); + ensure_equals("size() after skip()", strq.size(), leave); + size_t readlen(strq.read(&buffer[0], buffer.size())); + ensure_equals("read(\"craft\")", readlen, leave); + ensure_equals("read(\"craft\") result", + std::string(buffer.begin(), buffer.begin() + readlen), "craft"); + } + + template<> template<> + void object::test<5>() + { + set_test_name("concatenate blocks"); + std::string blocks[] = { "abcd", "efghij", "klmnopqrs" }; + BOOST_FOREACH(const std::string& block, blocks) + { + strq.write(&block[0], block.length()); + } + std::vector<char> longbuffer(30); + std::streamsize readlen(strq.read(&longbuffer[0], longbuffer.size())); + ensure_equals("read() multiple blocks", + readlen, blocks[0].length() + blocks[1].length() + blocks[2].length()); + ensure_equals("read() multiple blocks result", + std::string(longbuffer.begin(), longbuffer.begin() + readlen), + blocks[0] + blocks[1] + blocks[2]); + } + + template<> template<> + void object::test<6>() + { + set_test_name("split blocks"); + std::string blocks[] = { "abcdefghijklm", "nopqrstuvwxyz" }; + BOOST_FOREACH(const std::string& block, blocks) + { + strq.write(&block[0], block.length()); + } + strq.close(); + // We've already verified what strq.size() should be at this point; + // see above test named "skip() multiple blocks" + std::streamsize chksize(strq.size()); + std::streamsize readlen(strq.read(&buffer[0], buffer.size())); + ensure_equals("read() 0", readlen, buffer.size()); + ensure_equals("read() 0 result", std::string(buffer.begin(), buffer.end()), "abcdefghij"); + chksize -= readlen; + ensure_equals("size() after read() 0", strq.size(), chksize); + readlen = strq.read(&buffer[0], buffer.size()); + ensure_equals("read() 1", readlen, buffer.size()); + ensure_equals("read() 1 result", std::string(buffer.begin(), buffer.end()), "klmnopqrst"); + chksize -= readlen; + ensure_equals("size() after read() 1", strq.size(), chksize); + readlen = strq.read(&buffer[0], buffer.size()); + ensure_equals("read() 2", readlen, chksize); + ensure_equals("read() 2 result", + std::string(buffer.begin(), buffer.begin() + readlen), "uvwxyz"); + ensure_equals("read() 3", strq.read(&buffer[0], buffer.size()), -1); + } +} // namespace tut diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index 6a1cbf652a..93d3968dbf 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -29,7 +29,11 @@ #include "linden_common.h" #include "../test/lltut.h" +#include <boost/assign/list_of.hpp> #include "../llstring.h" +#include "StringVec.h" + +using boost::assign::list_of; namespace tut { @@ -750,4 +754,118 @@ namespace tut ensure("empty substr.", !LLStringUtil::endsWith(empty, value)); ensure("empty everything.", !LLStringUtil::endsWith(empty, empty)); } + + template<> template<> + void string_index_object_t::test<41>() + { + set_test_name("getTokens(\"delims\")"); + ensure_equals("empty string", LLStringUtil::getTokens("", " "), StringVec()); + ensure_equals("only delims", + LLStringUtil::getTokens(" \r\n ", " \r\n"), StringVec()); + ensure_equals("sequence of delims", + LLStringUtil::getTokens(",,, one ,,,", ","), list_of("one")); + // nat considers this a dubious implementation side effect, but I'd + // hate to change it now... + ensure_equals("noncontiguous tokens", + LLStringUtil::getTokens(", ,, , one ,,,", ","), list_of("")("")("one")); + ensure_equals("space-padded tokens", + LLStringUtil::getTokens(", one , two ,", ","), list_of("one")("two")); + ensure_equals("no delims", LLStringUtil::getTokens("one", ","), list_of("one")); + } + + // Shorthand for verifying that getTokens() behaves the same when you + // don't pass a string of escape characters, when you pass an empty string + // (different overloads), and when you pass a string of characters that + // aren't actually present. + void ensure_getTokens(const std::string& desc, + const std::string& string, + const std::string& drop_delims, + const std::string& keep_delims, + const std::string& quotes, + const std::vector<std::string>& expect) + { + ensure_equals(desc + " - no esc", + LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes), + expect); + ensure_equals(desc + " - empty esc", + LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes, ""), + expect); + ensure_equals(desc + " - unused esc", + LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes, "!"), + expect); + } + + void ensure_getTokens(const std::string& desc, + const std::string& string, + const std::string& drop_delims, + const std::string& keep_delims, + const std::vector<std::string>& expect) + { + ensure_getTokens(desc, string, drop_delims, keep_delims, "", expect); + } + + template<> template<> + void string_index_object_t::test<42>() + { + set_test_name("getTokens(\"delims\", etc.)"); + // Signatures to test in this method: + // getTokens(string, drop_delims, keep_delims [, quotes [, escapes]]) + // If you omit keep_delims, you get the older function (test above). + + // cases like the getTokens(string, delims) tests above + ensure_getTokens("empty string", "", " ", "", StringVec()); + ensure_getTokens("only delims", + " \r\n ", " \r\n", "", StringVec()); + ensure_getTokens("sequence of delims", + ",,, one ,,,", ", ", "", list_of("one")); + // Note contrast with the case in the previous method + ensure_getTokens("noncontiguous tokens", + ", ,, , one ,,,", ", ", "", list_of("one")); + ensure_getTokens("space-padded tokens", + ", one , two ,", ", ", "", + list_of("one")("two")); + ensure_getTokens("no delims", "one", ",", "", list_of("one")); + + // drop_delims vs. keep_delims + ensure_getTokens("arithmetic", + " ab+def / xx* yy ", " ", "+-*/", + list_of("ab")("+")("def")("/")("xx")("*")("yy")); + + // quotes + ensure_getTokens("no quotes", + "She said, \"Don't go.\"", " ", ",", "", + list_of("She")("said")(",")("\"Don't")("go.\"")); + ensure_getTokens("quotes", + "She said, \"Don't go.\"", " ", ",", "\"", + list_of("She")("said")(",")("Don't go.")); + ensure_getTokens("quotes and delims", + "run c:/'Documents and Settings'/someone", " ", "", "'", + list_of("run")("c:/Documents and Settings/someone")); + ensure_getTokens("unmatched quote", + "baby don't leave", " ", "", "'", + list_of("baby")("don't")("leave")); + ensure_getTokens("adjacent quoted", + "abc'def \"ghi'\"jkl' mno\"pqr", " ", "", "\"'", + list_of("abcdef \"ghijkl' mnopqr")); + ensure_getTokens("quoted empty string", + "--set SomeVar ''", " ", "", "'", + list_of("--set")("SomeVar")("")); + + // escapes + // Don't use backslash as an escape for these tests -- you'll go nuts + // between the C++ string scanner and getTokens() escapes. Test with + // something else! + ensure_equals("escaped delims", + LLStringUtil::getTokens("^ a - dog^-gone^ phrase", " ", "-", "", "^"), + list_of(" a")("-")("dog-gone phrase")); + ensure_equals("escaped quotes", + LLStringUtil::getTokens("say: 'this isn^'t w^orking'.", " ", "", "'", "^"), + list_of("say:")("this isn't working.")); + ensure_equals("escaped escape", + LLStringUtil::getTokens("want x^^2", " ", "", "", "^"), + list_of("want")("x^2")); + ensure_equals("escape at end", + LLStringUtil::getTokens("it's^ up there^", " ", "", "'", "^"), + list_of("it's up")("there^")); + } } diff --git a/indra/llcommon/tests/setpython.py b/indra/llcommon/tests/setpython.py deleted file mode 100644 index df7b90428e..0000000000 --- a/indra/llcommon/tests/setpython.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/python -"""\ -@file setpython.py -@author Nat Goodspeed -@date 2011-07-13 -@brief Set PYTHON environment variable for tests that care. - -$LicenseInfo:firstyear=2011&license=viewerlgpl$ -Copyright (c) 2011, Linden Research, Inc. -$/LicenseInfo$ -""" - -import os -import sys -import subprocess - -if __name__ == "__main__": - os.environ["PYTHON"] = sys.executable - sys.exit(subprocess.call(sys.argv[1:])) diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index ffda84729b..a4d3a4e026 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -29,7 +29,22 @@ #if ! defined(LL_WRAPLLERRS_H) #define LL_WRAPLLERRS_H +#if LL_WINDOWS +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif + +#include <tut/tut.hpp> #include "llerrorcontrol.h" +#include "stringize.h" +#include <boost/bind.hpp> +#include <boost/noncopyable.hpp> +#include <list> +#include <string> +#include <stdexcept> + +// statically reference the function in test.cpp... it's short, we could +// replicate, but better to reuse +extern void wouldHaveCrashed(const std::string& message); struct WrapLL_ERRS { @@ -70,4 +85,118 @@ struct WrapLL_ERRS LLError::FatalFunction mPriorFatal; }; +/** + * LLError::addRecorder() accepts ownership of the passed Recorder* -- it + * expects to be able to delete it later. CaptureLog isa Recorder whose + * pointer we want to be able to pass without any ownership implications. + * For such cases, instantiate a new RecorderProxy(yourRecorder) and pass + * that. Your heap RecorderProxy might later be deleted, but not yourRecorder. + */ +class RecorderProxy: public LLError::Recorder +{ +public: + RecorderProxy(LLError::Recorder* recorder): + mRecorder(recorder) + {} + + virtual void recordMessage(LLError::ELevel level, const std::string& message) + { + mRecorder->recordMessage(level, message); + } + + virtual bool wantsTime() + { + return mRecorder->wantsTime(); + } + +private: + LLError::Recorder* mRecorder; +}; + +/** + * Capture log messages. This is adapted (simplified) from the one in + * llerror_test.cpp. + */ +class CaptureLog : public LLError::Recorder, public boost::noncopyable +{ +public: + CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG): + // Mostly what we're trying to accomplish by saving and resetting + // LLError::Settings is to bypass the default RecordToStderr and + // RecordToWinDebug Recorders. As these are visible only inside + // llerror.cpp, we can't just call LLError::removeRecorder() with + // each. For certain tests we need to produce, capture and examine + // DEBUG log messages -- but we don't want to spam the user's console + // with that output. If it turns out that saveAndResetSettings() has + // some bad effect, give up and just let the DEBUG level log messages + // display. + mOldSettings(LLError::saveAndResetSettings()), + mProxy(new RecorderProxy(this)) + { + LLError::setFatalFunction(wouldHaveCrashed); + LLError::setDefaultLevel(level); + LLError::addRecorder(mProxy); + } + + ~CaptureLog() + { + LLError::removeRecorder(mProxy); + delete mProxy; + LLError::restoreSettings(mOldSettings); + } + + void recordMessage(LLError::ELevel level, + const std::string& message) + { + mMessages.push_back(message); + } + + /// Don't assume the message we want is necessarily the LAST log message + /// emitted by the underlying code; search backwards through all messages + /// for the sought string. + std::string messageWith(const std::string& search, bool required=true) + { + for (MessageList::const_reverse_iterator rmi(mMessages.rbegin()), rmend(mMessages.rend()); + rmi != rmend; ++rmi) + { + if (rmi->find(search) != std::string::npos) + return *rmi; + } + // failed to find any such message + if (! required) + return std::string(); + + throw tut::failure(STRINGIZE("failed to find '" << search + << "' in captured log messages:\n" + << boost::ref(*this))); + } + + std::ostream& streamto(std::ostream& out) const + { + MessageList::const_iterator mi(mMessages.begin()), mend(mMessages.end()); + if (mi != mend) + { + // handle first message separately: it doesn't get a newline + out << *mi++; + for ( ; mi != mend; ++mi) + { + // every subsequent message gets a newline + out << '\n' << *mi; + } + } + return out; + } + + typedef std::list<std::string> MessageList; + MessageList mMessages; + LLError::Settings* mOldSettings; + LLError::Recorder* mProxy; +}; + +inline +std::ostream& operator<<(std::ostream& out, const CaptureLog& log) +{ + return log.streamto(out); +} + #endif /* ! defined(LL_WRAPLLERRS_H) */ diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 3461aa3e6c..d6dcde4b9f 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -250,7 +250,7 @@ void LLCrashLogger::gatherFiles() if(minidump_stream.is_open()) { minidump_stream.seekg(0, std::ios::end); - size_t length = minidump_stream.tellg(); + size_t length = (size_t)minidump_stream.tellg(); minidump_stream.seekg(0, std::ios::beg); LLSD::Binary data; diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 56e01ac851..6775b005f4 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -48,11 +48,15 @@ //static std::string LLImage::sLastErrorMessage; LLMutex* LLImage::sMutex = NULL; +bool LLImage::sUseNewByteRange = false; +S32 LLImage::sMinimalReverseByteRangePercent = 75; LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ; //static -void LLImage::initClass() +void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) { + sUseNewByteRange = use_new_byte_range; + sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; sMutex = new LLMutex(NULL); LLImageBase::createPrivatePool() ; @@ -1334,7 +1338,8 @@ LLImageFormatted::LLImageFormatted(S8 codec) mCodec(codec), mDecoding(0), mDecoded(0), - mDiscardLevel(-1) + mDiscardLevel(-1), + mLevels(0) { mMemType = LLMemType::MTYPE_IMAGEFORMATTED; } @@ -1561,7 +1566,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size) //---------------------------------------------------------------------------- -BOOL LLImageFormatted::load(const std::string &filename) +BOOL LLImageFormatted::load(const std::string &filename, int load_size) { resetLastError(); @@ -1580,14 +1585,19 @@ BOOL LLImageFormatted::load(const std::string &filename) return FALSE; } + // Constrain the load size to acceptable values + if ((load_size == 0) || (load_size > file_size)) + { + load_size = file_size; + } BOOL res; - U8 *data = allocateData(file_size); - apr_size_t bytes_read = file_size; + U8 *data = allocateData(load_size); + apr_size_t bytes_read = load_size; apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read - if (s != APR_SUCCESS || (S32) bytes_read != file_size) + if (s != APR_SUCCESS || (S32) bytes_read != load_size) { deleteData(); - setLastError("Unable to read entire file",filename); + setLastError("Unable to read file",filename); res = FALSE; } else diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 4469c9e860..46e6d1a901 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -48,6 +48,8 @@ const S32 MAX_PRECINCT_SIZE = 2048; // No reason to be bigger than MAX_IMAGE_S const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec +const S32 MIN_LAYER_SIZE = 2000; // Size of the first quality layer (after header). Must be > to FIRST_PACKET_SIZE!! +const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit) const S32 MIN_IMAGE_SIZE = (1<<MIN_IMAGE_MIP); // 4, only used for expand/contract power of 2 const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 2048 @@ -60,6 +62,7 @@ const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; //2048 * // *TODO: change both to 1024 when SIM texture fetching is deprecated const S32 FIRST_PACKET_SIZE = 600; const S32 MAX_IMG_PACKET_SIZE = 1000; +const S32 HTTP_PACKET_SIZE = 1496; // Base classes for images. // There are two major parts for the image: @@ -89,15 +92,20 @@ typedef enum e_image_codec class LLImage { public: - static void initClass(); + static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); static void cleanupClass(); static const std::string& getLastError(); static void setLastError(const std::string& message); + static bool useNewByteRange() { return sUseNewByteRange; } + static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; } + protected: static LLMutex* sMutex; static std::string sLastErrorMessage; + static bool sUseNewByteRange; + static S32 sMinimalReverseByteRangePercent; }; //============================================================================ @@ -294,7 +302,7 @@ public: // getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C) virtual S8 getRawDiscardLevel() { return mDiscardLevel; } - BOOL load(const std::string& filename); + BOOL load(const std::string& filename, int load_size = 0); BOOL save(const std::string& filename); virtual BOOL updateData() = 0; // pure virtual @@ -313,6 +321,8 @@ public: BOOL isDecoded() const { return mDecoded ? TRUE : FALSE; } void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; } S8 getDiscardLevel() const { return mDiscardLevel; } + S8 getLevels() const { return mLevels; } + void setLevels(S8 nlevels) { mLevels = nlevels; } // setLastError needs to be deferred for J2C images since it may be called from a DLL virtual void resetLastError(); @@ -325,7 +335,8 @@ protected: S8 mCodec; S8 mDecoding; S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC - S8 mDiscardLevel; + S8 mDiscardLevel; // Current resolution level worked on. 0 = full res, 1 = half res, 2 = quarter res, etc... + S8 mLevels; // Number of resolution levels in that image. Min is 1. 0 means unknown. public: static S32 sGlobalFormattedMemory; diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index cc8cb66d73..452aad25cb 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -56,7 +56,7 @@ std::string LLImageJ2C::getEngineInfo() LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C), mMaxBytes(0), mRawDiscardLevel(-1), - mRate(0.0f), + mRate(DEFAULT_COMPRESSION_RATE), mReversible(FALSE), mAreaUsedForDataSizeCalcs(0) { @@ -142,6 +142,7 @@ BOOL LLImageJ2C::updateData() BOOL LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region) { + setDiscardLevel(discard_level != -1 ? discard_level : 0); return mImpl->initDecode(*this,raw_image,discard_level,region); } @@ -261,19 +262,34 @@ S32 LLImageJ2C::calcHeaderSizeJ2C() //static S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate) { - // Note: this only provides an *estimate* of the size in bytes of an image level - // *TODO: find a way to read the true size (when available) and convey the fact - // that the result is an estimate in the other cases - if (rate <= 0.f) rate = .125f; - while (discard_level > 0) + // Note: This provides an estimation for the first to last quality layer of a given discard level + // This is however an efficient approximation, as the true discard level boundary would be + // in general too big for fast fetching. + // For details about the equation used here, see https://wiki.lindenlab.com/wiki/THX1138_KDU_Improvements#Byte_Range_Study + + // Estimate the number of layers. This is consistent with what's done for j2c encoding in LLImageJ2CKDU::encodeImpl(). + S32 nb_layers = 1; + S32 surface = w*h; + S32 s = 64*64; + while (surface > s) { - if (w < 1 || h < 1) - break; - w >>= 1; - h >>= 1; - discard_level--; + nb_layers++; + s *= 4; } - S32 bytes = (S32)((F32)(w*h*comp)*rate); + F32 layer_factor = 3.0f * (7 - llclamp(nb_layers,1,6)); + + // Compute w/pow(2,discard_level) and h/pow(2,discard_level) + w >>= discard_level; + h >>= discard_level; + w = llmax(w, 1); + h = llmax(h, 1); + + // Temporary: compute both new and old range and pick one according to the settings TextureNewByteRange + // *TODO: Take the old code out once we have enough tests done + S32 bytes; + S32 new_bytes = (S32) (sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/layer_factor); + S32 old_bytes = (S32)((F32)(w*h*comp)*rate); + bytes = (LLImage::useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes); bytes = llmax(bytes, calcHeaderSizeJ2C()); return bytes; } @@ -283,15 +299,12 @@ S32 LLImageJ2C::calcHeaderSize() return calcHeaderSizeJ2C(); } - -// calcDataSize() returns how many bytes to read -// to load discard_level (including header and higher discard levels) +// calcDataSize() returns how many bytes to read to load discard_level (including header) S32 LLImageJ2C::calcDataSize(S32 discard_level) { discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL); - if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth()) - || mDataSizes[0] == 0) + || (mDataSizes[0] == 0)) { mAreaUsedForDataSizeCalcs = getHeight() * getWidth(); @@ -301,25 +314,6 @@ S32 LLImageJ2C::calcDataSize(S32 discard_level) mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate); level--; } - - /* This is technically a more correct way to calculate the size required - for each discard level, since they should include the size needed for - lower levels. Unfortunately, this doesn't work well and will lead to - download stalls. The true correct way is to parse the header. This will - all go away with http textures at some point. - - // Calculate the size for each discard level. Lower levels (higher quality) - // contain the cumulative size of higher levels - S32 total_size = calcHeaderSizeJ2C(); - - S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard - while ( level >= 0 ) - { // Add in this discard level and all before it - total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate); - mDataSizes[level] = total_size; - level--; - } - */ } return mDataSizes[discard_level]; } @@ -334,8 +328,9 @@ S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes) } while (1) { - S32 bytes_needed = calcDataSize(discard_level); // virtual - if (bytes >= bytes_needed - (bytes_needed>>2)) // For J2c, up the res at 75% of the optimal number of bytes + S32 bytes_needed = calcDataSize(discard_level); + // Use TextureReverseByteRange percent (see settings.xml) of the optimal size to qualify as correct rendering for the given discard level + if (bytes >= (bytes_needed*LLImage::getReverseByteRangePercent()/100)) { break; } @@ -348,11 +343,6 @@ S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes) return discard_level; } -void LLImageJ2C::setRate(F32 rate) -{ - mRate = rate; -} - void LLImageJ2C::setMaxBytes(S32 max_bytes) { mMaxBytes = max_bytes; @@ -474,6 +464,7 @@ LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTester addMetric("Perf Compression (kB/s)"); mRunBytesInDecompression = 0; + mRunBytesOutDecompression = 0; mRunBytesInCompression = 0; mTotalBytesInDecompression = 0; @@ -483,6 +474,7 @@ LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTester mTotalTimeDecompression = 0.0f; mTotalTimeCompression = 0.0f; + mRunTimeDecompression = 0.0f; } LLImageCompressionTester::~LLImageCompressionTester() @@ -501,10 +493,10 @@ void LLImageCompressionTester::outputTestRecord(LLSD *sd) F32 decompressionRate = 0.0f; F32 compressionRate = 0.0f; - F32 totalkBInDecompression = (F32)(mTotalBytesInDecompression) / 1000.0; - F32 totalkBOutDecompression = (F32)(mTotalBytesOutDecompression) / 1000.0; - F32 totalkBInCompression = (F32)(mTotalBytesInCompression) / 1000.0; - F32 totalkBOutCompression = (F32)(mTotalBytesOutCompression) / 1000.0; + F32 totalkBInDecompression = (F32)(mTotalBytesInDecompression) / 1000.f; + F32 totalkBOutDecompression = (F32)(mTotalBytesOutDecompression) / 1000.f; + F32 totalkBInCompression = (F32)(mTotalBytesInCompression) / 1000.f; + F32 totalkBOutCompression = (F32)(mTotalBytesOutCompression) / 1000.f; if (!is_approx_zero(mTotalTimeDecompression)) { @@ -565,12 +557,17 @@ void LLImageCompressionTester::updateDecompressionStats(const S32 bytesIn, const mTotalBytesInDecompression += bytesIn; mRunBytesInDecompression += bytesIn; mTotalBytesOutDecompression += bytesOut; - if (mRunBytesInDecompression > (1000000)) + mRunBytesOutDecompression += bytesOut; + //if (mRunBytesInDecompression > (1000000)) + if (mRunBytesOutDecompression > (10000000)) + //if ((mTotalTimeDecompression - mRunTimeDecompression) >= (5.0f)) { // Output everything outputTestResults(); // Reset the decompression data of the run mRunBytesInDecompression = 0; + mRunBytesOutDecompression = 0; + mRunTimeDecompression = mTotalTimeDecompression; } } diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h index 914174fc57..ce8195940d 100644 --- a/indra/llimage/llimagej2c.h +++ b/indra/llimage/llimagej2c.h @@ -31,6 +31,9 @@ #include "llassettype.h" #include "llmetricperformancetester.h" +// JPEG2000 : compression rate used in j2c conversion. +const F32 DEFAULT_COMPRESSION_RATE = 1.f/8.f; + class LLImageJ2CImpl; class LLImageCompressionTester ; @@ -67,12 +70,11 @@ public: // Encode accessors void setReversible(const BOOL reversible); // Use non-lossy? - void setRate(F32 rate); void setMaxBytes(S32 max_bytes); S32 getMaxBytes() const { return mMaxBytes; } static S32 calcHeaderSizeJ2C(); - static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = 0.f); + static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = DEFAULT_COMPRESSION_RATE); static std::string getEngineInfo(); @@ -154,13 +156,15 @@ class LLImageCompressionTester : public LLMetricPerformanceTesterBasic U32 mTotalBytesOutDecompression; // Total bytes produced by decompressor U32 mTotalBytesInCompression; // Total bytes fed to compressor U32 mTotalBytesOutCompression; // Total bytes produced by compressor - U32 mRunBytesInDecompression; // Bytes fed to decompressor in this run + U32 mRunBytesInDecompression; // Bytes fed to decompressor in this run + U32 mRunBytesOutDecompression; // Bytes produced by the decompressor in this run U32 mRunBytesInCompression; // Bytes fed to compressor in this run // // Time // F32 mTotalTimeDecompression; // Total time spent in computing decompression F32 mTotalTimeCompression; // Total time spent in computing compression + F32 mRunTimeDecompression; // Time in this run (we output every 5 sec in decompress) }; #endif diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp index 8d493ecde0..294f68b122 100644 --- a/indra/llimage/llimagepng.cpp +++ b/indra/llimage/llimagepng.cpp @@ -60,6 +60,12 @@ BOOL LLImagePNG::updateData() // Decode the PNG data and extract sizing information LLPngWrapper pngWrapper; + if (!pngWrapper.isValidPng(getData())) + { + setLastError("LLImagePNG data does not have a valid PNG header!"); + return FALSE; + } + LLPngWrapper::ImageInfo infop; if (! pngWrapper.readPng(getData(), NULL, &infop)) { @@ -90,6 +96,12 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time) // Decode the PNG data into the raw image LLPngWrapper pngWrapper; + if (!pngWrapper.isValidPng(getData())) + { + setLastError("LLImagePNG data does not have a valid PNG header!"); + return FALSE; + } + if (! pngWrapper.readPng(getData(), raw_image)) { setLastError(pngWrapper.getErrorMessage()); diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 76760aa414..fbf23bc3f0 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -405,7 +405,7 @@ U32 LLInventoryItem::getCRC32() const //lldebugs << "7 crc: " << std::hex << crc << std::dec << llendl; crc += mSaleInfo.getCRC32(); //lldebugs << "8 crc: " << std::hex << crc << std::dec << llendl; - crc += mCreationDate; + crc += (U32)mCreationDate; //lldebugs << "9 crc: " << std::hex << crc << std::dec << llendl; return crc; } @@ -521,7 +521,7 @@ void LLInventoryItem::packMessage(LLMessageSystem* msg) const mSaleInfo.packMessage(msg); msg->addStringFast(_PREHASH_Name, mName); msg->addStringFast(_PREHASH_Description, mDescription); - msg->addS32Fast(_PREHASH_CreationDate, mCreationDate); + msg->addS32Fast(_PREHASH_CreationDate, (S32)mCreationDate); U32 crc = getCRC32(); msg->addU32Fast(_PREHASH_CRC, crc); } 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/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index c156ed0cef..cf88de12b4 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -32,6 +32,7 @@ #include "llmath.h" #include "llkdumem.h" +#include "kdu_block_coding.h" class kdc_flow_control { @@ -244,7 +245,9 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod mCodeStreamp->create(mInputp); // Set the maximum number of bytes to use from the codestream - mCodeStreamp->set_max_bytes(max_bytes); + // *TODO: This seems to be wrong. The base class should have no idea of how j2c compression works so no + // good way of computing what's the byte range to be used. + mCodeStreamp->set_max_bytes(max_bytes,true); // If you want to flip or rotate the image for some reason, change // the resolution, or identify a restricted region of interest, this is @@ -291,8 +294,13 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod } } + // Get the number of resolution levels in that image + mLevels = mCodeStreamp->get_min_dwt_levels(); + + // Set the base dimensions base.setSize(dims.size.x, dims.size.y, components); - + base.setLevels(mLevels); + if (!keep_codestream) { mCodeStreamp->destroy(); @@ -351,7 +359,8 @@ BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc mLevels = levels; if (mLevels != 0) { - mLevels = llclamp(mLevels,MIN_DECOMPOSITION_LEVELS,MIN_DECOMPOSITION_LEVELS); + mLevels = llclamp(mLevels,MIN_DECOMPOSITION_LEVELS,MAX_DECOMPOSITION_LEVELS); + base.setLevels(mLevels); } return TRUE; } @@ -364,6 +373,9 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco // To regain control, we throw an exception, and catch it here. try { + // Merov : Test!! DO NOT COMMIT!! + //findDiscardLevelsBoundaries(base); + base.updateRawDiscardLevel(); setupCodeStream(base, TRUE, mode); @@ -381,7 +393,7 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco region_kdu->size.y = region[3] - region[1]; } int discard = (discard_level != -1 ? discard_level : base.getRawDiscardLevel()); - + //llinfos << "Merov debug : initDecode, discard used = " << discard << ", asked = " << discard_level << llendl; // Apply loading restrictions mCodeStreamp->apply_input_restrictions( first_channel, max_channel_count, discard, 0, region_kdu); @@ -394,12 +406,9 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco // Resize raw_image according to the image to be decoded kdu_dims dims; mCodeStreamp->get_dims(0,dims); - // *TODO: Use the real number of levels read from the file throughout the code instead of relying on an infered value from dimensions - //S32 levels = mCodeStreamp->get_min_dwt_levels(); S32 channels = base.getComponents() - first_channel; channels = llmin(channels,max_channel_count); raw_image.resize(dims.size.x, dims.size.y, channels); - //llinfos << "j2c image dimension: width = " << dims.size.x << ", height = " << dims.size.y << ", channels = " << channels << ", levels = " << levels << llendl; if (!mTileIndicesp) { @@ -583,12 +592,6 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co comment.put_text(comment_text); } - // Set codestream options - int num_layer_specs = 0; - - kdu_long layer_bytes[64]; - U32 max_bytes = 0; - if (num_components >= 3) { // Note that we always use YCC and not YUV @@ -596,66 +599,51 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co set_default_colour_weights(codestream.access_siz()); } - if (reversible) + // Set codestream options + int nb_layers = 0; + kdu_long layer_bytes[MAX_NB_LAYERS]; + U32 max_bytes = (U32)(base.getWidth() * base.getHeight() * base.getComponents()); + + // Rate is the argument passed into the LLImageJ2C which specifies the target compression rate. The default is 8:1. + // *TODO: mRate is actually always 8:1 in the viewer. Test different values. + llassert (base.mRate > 0.f); + max_bytes = (U32)((F32)(max_bytes) * base.mRate); + + // This code is where we specify the target number of bytes for each quality layer. + // We're using a logarithmic spacing rule that fits with our way of fetching texture data. + // Note: For more info on this layers business, read kdu_codestream::flush() doc in kdu_compressed.h + layer_bytes[nb_layers++] = FIRST_PACKET_SIZE; + U32 i = MIN_LAYER_SIZE; + while ((i < max_bytes) && (nb_layers < (MAX_NB_LAYERS-1))) { - codestream.access_siz()->parse_string("Creversible=yes"); - // *TODO: we should use yuv in reversible mode and one level since those images are small. - // Don't turn this on now though as both create problems on decoding for the moment - //codestream.access_siz()->parse_string("Clevels=1"); - //codestream.access_siz()->parse_string("Cycc=no"); - // If we're doing reversible (i.e. lossless compression), assumes we're not using quality layers. - // *TODO: this is incorrect and unecessary. Try using the regular layer setting. - codestream.access_siz()->parse_string("Clayers=1"); - num_layer_specs = 1; - layer_bytes[0] = 0; + layer_bytes[nb_layers++] = i; + i *= 4; } - else + // Note: for small images, we can have (max_bytes < FIRST_PACKET_SIZE), hence the test + if (layer_bytes[nb_layers-1] < max_bytes) { - // Rate is the argument passed into the LLImageJ2C which - // specifies the target compression rate. The default is 8:1. - // Possibly if max_bytes < 500, we should just use the default setting? - // *TODO: mRate is actually always 8:1 in the viewer. Test different values. Also force to reversible for small (< 500 bytes) textures. - if (base.mRate != 0.f) - { - max_bytes = (U32)(base.mRate*base.getWidth()*base.getHeight()*base.getComponents()); - } - else - { - max_bytes = (U32)(base.getWidth()*base.getHeight()*base.getComponents()*0.125); - } - - const U32 min_bytes = FIRST_PACKET_SIZE; - if (max_bytes > min_bytes) - { - U32 i; - // This code is where we specify the target number of bytes for - // each layer. Not sure if we should do this for small images - // or not. The goal is to have this roughly align with - // different quality levels that we decode at. - for (i = min_bytes; i < max_bytes; i*=4) - { - if (i == min_bytes * 4) - { - i = 2000; - } - layer_bytes[num_layer_specs] = i; - num_layer_specs++; - } - layer_bytes[num_layer_specs] = max_bytes; - num_layer_specs++; + // Set the last quality layer so to fit the preset compression ratio + layer_bytes[nb_layers++] = max_bytes; + } - std::string layer_string = llformat("Clayers=%d",num_layer_specs); - codestream.access_siz()->parse_string(layer_string.c_str()); - } - else + if (reversible) + { + // Use 0 for a last quality layer for reversible images so all remaining code blocks will be flushed + // Hack: KDU encoding for reversible images has a bug for small images that leads to j2c images that + // cannot be open or are very blurry. Avoiding that last layer prevents the problem to happen. + if ((base.getWidth() >= 32) || (base.getHeight() >= 32)) { - layer_bytes[0] = min_bytes; - num_layer_specs = 1; - std::string layer_string = llformat("Clayers=%d",num_layer_specs); - codestream.access_siz()->parse_string(layer_string.c_str()); + layer_bytes[nb_layers++] = 0; } + codestream.access_siz()->parse_string("Creversible=yes"); + // *TODO: we should use yuv in reversible mode + // Don't turn this on now though as it creates problems on decoding for the moment + //codestream.access_siz()->parse_string("Cycc=no"); } + std::string layer_string = llformat("Clayers=%d",nb_layers); + codestream.access_siz()->parse_string(layer_string.c_str()); + // Set up data ordering, markers, etc... if precincts or blocks specified if ((mBlocksSize != -1) || (mPrecinctsSize != -1)) { @@ -669,23 +657,26 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co std::string blocks_string = llformat("Cblk={%d,%d}",mBlocksSize,mBlocksSize); codestream.access_siz()->parse_string(blocks_string.c_str()); } - std::string ordering_string = llformat("Corder=RPCL"); + std::string ordering_string = llformat("Corder=LRCP"); codestream.access_siz()->parse_string(ordering_string.c_str()); std::string PLT_string = llformat("ORGgen_plt=yes"); codestream.access_siz()->parse_string(PLT_string.c_str()); std::string Parts_string = llformat("ORGtparts=R"); codestream.access_siz()->parse_string(Parts_string.c_str()); } + + // Set the number of wavelets subresolutions (aka levels) if (mLevels != 0) { std::string levels_string = llformat("Clevels=%d",mLevels); codestream.access_siz()->parse_string(levels_string.c_str()); } + // Complete the encode settings codestream.access_siz()->finalize_all(); codestream.change_appearance(transpose,vflip,hflip); - // Now we are ready for sample data processing. + // Now we are ready for sample data processing kdc_flow_control *tile = new kdc_flow_control(&mem_in,codestream); bool done = false; while (!done) @@ -702,7 +693,7 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co } // Produce the compressed output - codestream.flush(layer_bytes,num_layer_specs); + codestream.flush(layer_bytes,nb_layers); // Cleanup delete tile; @@ -750,6 +741,207 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) } } +/*****************************************************************************/ +/* STATIC copy_block */ +/*****************************************************************************/ + +static void copy_block(kdu_block *in, kdu_block *out) +{ + if (in->K_max_prime != out->K_max_prime) + { + std::cout << "Cannot copy blocks belonging to subbands with different quantization parameters." << std::endl; + return; + } + if ((in->size.x != out->size.x) || (in->size.y != out->size.y)) + { + std::cout << "Cannot copy code-blocks with different dimensions." << std::endl; + return; + } + out->missing_msbs = in->missing_msbs; + if (out->max_passes < (in->num_passes+2)) // Gives us enough to round up + out->set_max_passes(in->num_passes+2,false); // to the next whole bit-plane + out->num_passes = in->num_passes; + int num_bytes = 0; + for (int z=0; z < in->num_passes; z++) + { + num_bytes += (out->pass_lengths[z] = in->pass_lengths[z]); + out->pass_slopes[z] = in->pass_slopes[z]; + } + + // Just copy compressed code-bytes. Block transcoding not supported. + if (out->max_bytes < num_bytes) + out->set_max_bytes(num_bytes,false); + memcpy(out->byte_buffer,in->byte_buffer,(size_t) num_bytes); +} + +/*****************************************************************************/ +/* STATIC copy_tile */ +/*****************************************************************************/ + +static void +copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out, + kdu_params *siz_in, kdu_params *siz_out, int skip_components, + int &num_blocks) +{ + int num_components = tile_out.get_num_components(); + int new_tpart=0, next_tpart = 1; + + for (int c=0; c < num_components; c++) + { + kdu_tile_comp comp_in, comp_out; + comp_in = tile_in.access_component(c); + comp_out = tile_out.access_component(c); + int num_resolutions = comp_out.get_num_resolutions(); + //std::cout << " Copying tile : num_resolutions = " << num_resolutions << std::endl; + for (int r=0; r < num_resolutions; r++) + { + kdu_resolution res_in; res_in = comp_in.access_resolution(r); + kdu_resolution res_out; res_out = comp_out.access_resolution(r); + int b, min_band; + int num_bands = res_in.get_valid_band_indices(min_band); + std::cout << " Copying tile : num_bands = " << num_bands << std::endl; + for (b=min_band; num_bands > 0; num_bands--, b++) + { + kdu_subband band_in; band_in = res_in.access_subband(b); + kdu_subband band_out; band_out = res_out.access_subband(b); + kdu_dims blocks_in; band_in.get_valid_blocks(blocks_in); + kdu_dims blocks_out; band_out.get_valid_blocks(blocks_out); + if ((blocks_in.size.x != blocks_out.size.x) || + (blocks_in.size.y != blocks_out.size.y)) + { + std::cout << "Transcoding operation cannot proceed: Code-block partitions for the input and output code-streams do not agree." << std::endl; + return; + } + kdu_coords idx; + //std::cout << " Copying tile : block indices, x = " << blocks_out.size.x << " and y = " << blocks_out.size.y << std::endl; + for (idx.y=0; idx.y < blocks_out.size.y; idx.y++) + { + for (idx.x=0; idx.x < blocks_out.size.x; idx.x++) + { + kdu_block *in = + band_in.open_block(idx+blocks_in.pos,&new_tpart); + for (; next_tpart <= new_tpart; next_tpart++) + siz_out->copy_from(siz_in,tnum_in,tnum_out,next_tpart, + skip_components); + kdu_block *out = band_out.open_block(idx+blocks_out.pos); + copy_block(in,out); + band_in.close_block(in); + band_out.close_block(out); + num_blocks++; + } + } + } + } + } +} + +// Find the block boundary for each discard level in the input image. +// We parse the input blocks and copy them in a temporary output stream. +// For the moment, we do nothing more that parsing the raw list of blocks and outputing result. +void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base) +{ + // We need the number of levels in that image before starting. + getMetadata(base); + + for (int discard_level = 0; discard_level < mLevels; discard_level++) + { + //std::cout << "Parsing discard level = " << discard_level << std::endl; + // Create the input codestream object. + setupCodeStream(base, TRUE, MODE_FAST); + mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL); + mCodeStreamp->set_max_bytes(KDU_LONG_MAX,true); + siz_params *siz_in = mCodeStreamp->access_siz(); + + // Create the output codestream object. + siz_params siz; + siz.copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false); + siz.set(Scomponents,0,0,mCodeStreamp->get_num_components()); + + U32 max_output_size = base.getWidth()*base.getHeight()*base.getComponents(); + max_output_size = (max_output_size < 1000 ? 1000 : max_output_size); + U8 *output_buffer = new U8[max_output_size]; + U32 output_size = 0; // Address updated by LLKDUMemTarget to give the final compressed buffer size + LLKDUMemTarget output(output_buffer, output_size, max_output_size); + kdu_codestream codestream_out; + codestream_out.create(&siz,&output); + //codestream_out.share_buffering(*mCodeStreamp); + siz_params *siz_out = codestream_out.access_siz(); + siz_out->copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false); + codestream_out.access_siz()->finalize_all(-1); + + // Set up rate control variables + kdu_long max_bytes = KDU_LONG_MAX; + kdu_params *cod = siz_out->access_cluster(COD_params); + int total_layers; cod->get(Clayers,0,0,total_layers); + kdu_long *layer_bytes = new kdu_long[total_layers]; + int nel, non_empty_layers = 0; + + // Now ready to perform the transfer of compressed data between streams + int flush_counter = INT_MAX; + kdu_dims tile_indices_in; + mCodeStreamp->get_valid_tiles(tile_indices_in); + kdu_dims tile_indices_out; + codestream_out.get_valid_tiles(tile_indices_out); + assert((tile_indices_in.size.x == tile_indices_out.size.x) && + (tile_indices_in.size.y == tile_indices_out.size.y)); + int num_blocks=0; + + kdu_coords idx; + //std::cout << "Parsing tiles : x = " << tile_indices_out.size.x << " to y = " << tile_indices_out.size.y << std::endl; + for (idx.y=0; idx.y < tile_indices_out.size.y; idx.y++) + { + for (idx.x=0; idx.x < tile_indices_out.size.x; idx.x++) + { + kdu_tile tile_in = mCodeStreamp->open_tile(idx+tile_indices_in.pos); + int tnum_in = tile_in.get_tnum(); + int tnum_out = idx.x + idx.y*tile_indices_out.size.x; + siz_out->copy_from(siz_in,tnum_in,tnum_out,0,0,discard_level,false,false,false); + siz_out->finalize_all(tnum_out); + // Note: do not open the output tile without first copying any tile-specific code-stream parameters + kdu_tile tile_out = codestream_out.open_tile(idx+tile_indices_out.pos); + assert(tnum_out == tile_out.get_tnum()); + copy_tile(tile_in,tile_out,tnum_in,tnum_out,siz_in,siz_out,0,num_blocks); + tile_in.close(); + tile_out.close(); + flush_counter--; + if ((flush_counter <= 0) && codestream_out.ready_for_flush()) + { + flush_counter = INT_MAX; + nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers); + non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers; + } + } + } + + // Generate the output code-stream + if (codestream_out.ready_for_flush()) + { + nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers); + non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers; + } + if (non_empty_layers > total_layers) + non_empty_layers = total_layers; // Can happen if a tile has more layers + + // Print out stats + std::cout << "Code stream parsing for discard level = " << discard_level << std::endl; + std::cout << " Total compressed memory in = " << mCodeStreamp->get_compressed_data_memory() << " bytes" << std::endl; + std::cout << " Total compressed memory out = " << codestream_out.get_compressed_data_memory() << " bytes" << std::endl; + //std::cout << " Output contains " << total_layers << " quality layers" << std::endl; + std::cout << " Transferred " << num_blocks << " code-blocks from in to out" << std::endl; + //std::cout << " Read " << mCodeStreamp->get_num_tparts() << " tile-part(s) from a total of " << (int) tile_indices_in.area() << " tile(s)" << std::endl; + std::cout << " Total bytes read = " << mCodeStreamp->get_total_bytes() << std::endl; + //std::cout << " Wrote " << codestream_out.get_num_tparts() << " tile-part(s) in a total of " << (int) tile_indices_out.area() << " tile(s)" << std::endl; + std::cout << " Total bytes written = " << codestream_out.get_total_bytes() << std::endl; + std::cout << "-------------" << std::endl; + + // Clean-up + cleanupCodeStream(); + codestream_out.destroy(); + delete[] output_buffer; + } + return; +} + void set_default_colour_weights(kdu_params *siz) { kdu_params *cod = siz->access_cluster(COD_params); diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h index 1489dbf704..9ab0b9e4a7 100644 --- a/indra/llkdu/llimagej2ckdu.h +++ b/indra/llkdu/llimagej2ckdu.h @@ -60,6 +60,7 @@ protected: BOOL reversible=FALSE); /*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL); /*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0); + void findDiscardLevelsBoundaries(LLImageJ2C &base); private: BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL); diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp index ab60ab6d50..beee99a522 100644 --- a/indra/llkdu/tests/llimagej2ckdu_test.cpp +++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp @@ -29,6 +29,7 @@ // Class to test #include "llimagej2ckdu.h" #include "llkdumem.h" +#include "kdu_block_coding.h" // Tut header #include "lltut.h" @@ -86,7 +87,7 @@ void LLImageFormatted::resetLastError() { } void LLImageFormatted::sanityCheck() { } void LLImageFormatted::setLastError(const std::string& , const std::string& ) { } -LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C) { } +LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C), mRate(DEFAULT_COMPRESSION_RATE) { } LLImageJ2C::~LLImageJ2C() { } S32 LLImageJ2C::calcDataSize(S32 ) { return 0; } S32 LLImageJ2C::calcDiscardLevelBytes(S32 ) { return 0; } @@ -107,16 +108,25 @@ bool LLKDUMemIn::get(int, kdu_line_buf&, int) { return false; } // Stub Kakadu Library calls kdu_tile_comp kdu_tile::access_component(int ) { kdu_tile_comp a; return a; } +kdu_block_encoder::kdu_block_encoder() { } +kdu_block_decoder::kdu_block_decoder() { } +void kdu_block::set_max_passes(int , bool ) { } +void kdu_block::set_max_bytes(int , bool ) { } +void kdu_block::set_max_samples(int ) { } void kdu_tile::close(kdu_thread_env* ) { } int kdu_tile::get_num_components() { return 0; } bool kdu_tile::get_ycc() { return false; } void kdu_tile::set_components_of_interest(int , const int* ) { } +int kdu_tile::get_tnum() { return 0; } kdu_resolution kdu_tile_comp::access_resolution() { kdu_resolution a; return a; } +kdu_resolution kdu_tile_comp::access_resolution(int ) { kdu_resolution a; return a; } int kdu_tile_comp::get_bit_depth(bool ) { return 8; } bool kdu_tile_comp::get_reversible() { return false; } +int kdu_tile_comp::get_num_resolutions() { return 1; } kdu_subband kdu_resolution::access_subband(int ) { kdu_subband a; return a; } void kdu_resolution::get_dims(kdu_dims& ) { } int kdu_resolution::which() { return 0; } +int kdu_resolution::get_valid_band_indices(int &) { return 1; } kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { } kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { } kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { } @@ -124,6 +134,7 @@ kdu_params::~kdu_params() { } void kdu_params::set(const char* , int , int , bool ) { } void kdu_params::set(const char* , int , int , int ) { } void kdu_params::finalize_all(bool ) { } +void kdu_params::finalize_all(int, bool ) { } void kdu_params::copy_from(kdu_params*, int, int, int, int, int, bool, bool, bool) { } bool kdu_params::parse_string(const char*) { return false; } bool kdu_params::get(const char*, int, int, bool&, bool, bool, bool) { return false; } @@ -135,6 +146,7 @@ void kdu_codestream::set_fast() { } void kdu_codestream::set_fussy() { } void kdu_codestream::get_dims(int, kdu_dims&, bool ) { } int kdu_codestream::get_min_dwt_levels() { return 5; } +int kdu_codestream::get_max_tile_layers() { return 1; } void kdu_codestream::change_appearance(bool, bool, bool) { } void kdu_codestream::get_tile_dims(kdu_coords, int, kdu_dims&, bool ) { } void kdu_codestream::destroy() { } @@ -148,9 +160,18 @@ void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { } void kdu_codestream::flush(kdu_long *, int , kdu_uint16 *, bool, bool, double, kdu_thread_env*) { } void kdu_codestream::set_resilient(bool ) { } int kdu_codestream::get_num_components(bool ) { return 0; } +kdu_long kdu_codestream::get_total_bytes(bool ) { return 0; } +kdu_long kdu_codestream::get_compressed_data_memory(bool ) {return 0; } +void kdu_codestream::share_buffering(kdu_codestream ) { } +int kdu_codestream::get_num_tparts() { return 0; } +int kdu_codestream::trans_out(kdu_long, kdu_long*, int, bool, kdu_thread_env* ) { return 0; } +bool kdu_codestream::ready_for_flush(kdu_thread_env*) { return false; } siz_params* kdu_codestream::access_siz() { return NULL; } kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; } kdu_codestream_comment kdu_codestream::add_comment() { kdu_codestream_comment a; return a; } +void kdu_subband::close_block(kdu_block*, kdu_thread_env*) { } +void kdu_subband::get_valid_blocks(kdu_dims &indices) { } +kdu_block* kdu_subband::open_block(kdu_coords, int*, kdu_thread_env*) { return NULL; } bool kdu_codestream_comment::put_text(const char*) { return false; } void kdu_customize_warnings(kdu_message*) { } void kdu_customize_errors(kdu_message*) { } diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index bd9c8c2519..e0ad270266 100644 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h @@ -174,7 +174,7 @@ private: F32 _log(const F32& a) const { return log(a); } F32 _exp(const F32& a) const { return exp(a); } F32 _fabs(const F32& a) const { return fabs(a); } - F32 _floor(const F32& a) const { return llfloor(a); } + F32 _floor(const F32& a) const { return (F32)llfloor(a); } F32 _ceil(const F32& a) const { return llceil(a); } F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h index 706ad92787..9b76268afd 100644 --- a/indra/llmath/llcoord.h +++ b/indra/llmath/llcoord.h @@ -26,80 +26,87 @@ #ifndef LL_LLCOORD_H #define LL_LLCOORD_H +template<typename> class LLCoord; +struct LL_COORD_TYPE_GL; +struct LL_COORD_TYPE_WINDOW; +struct LL_COORD_TYPE_SCREEN; + +typedef LLCoord<LL_COORD_TYPE_GL> LLCoordGL; +typedef LLCoord<LL_COORD_TYPE_WINDOW> LLCoordWindow; +typedef LLCoord<LL_COORD_TYPE_SCREEN> LLCoordScreen; + +struct LLCoordCommon +{ + LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {} + LLCoordCommon() : mX(0), mY(0) {} + S32 mX; + S32 mY; +}; + // A two-dimensional pixel value -class LLCoord +template<typename COORD_FRAME> +class LLCoord : protected COORD_FRAME { public: - S32 mX; - S32 mY; + typedef LLCoord<COORD_FRAME> self_t; + typename COORD_FRAME::value_t mX; + typename COORD_FRAME::value_t mY; LLCoord(): mX(0), mY(0) {} - LLCoord(S32 x, S32 y): mX(x), mY(y) - {} - virtual ~LLCoord() + LLCoord(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y): mX(x), mY(y) {} - virtual void set(S32 x, S32 y) { mX = x; mY = y; } -}; + LLCoord(const LLCoordCommon& other) + { + COORD_FRAME::convertFromCommon(other); + } + LLCoordCommon convert() const + { + return COORD_FRAME::convertToCommon(); + } -// GL coordinates start in the client region of a window, -// with left, bottom = 0, 0 -class LLCoordGL : public LLCoord -{ -public: - LLCoordGL() : LLCoord() - {} - LLCoordGL(S32 x, S32 y) : LLCoord(x, y) - {} - bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const LLCoordGL& other) const { return !(*this == other); } -}; + void set(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y) { mX = x; mY = y;} + bool operator==(const self_t& other) const { return mX == other.mX && mY == other.mY; } + bool operator!=(const self_t& other) const { return !(*this == other); } -//bool operator ==(const LLCoordGL& a, const LLCoordGL& b); + static const self_t& getTypedCoords(const COORD_FRAME& self) { return static_cast<const self_t&>(self); } + static self_t& getTypedCoords(COORD_FRAME& self) { return static_cast<self_t&>(self); } +}; -// Window coords include things like window borders, -// menu regions, etc. -class LLCoordWindow : public LLCoord +struct LL_COORD_TYPE_GL { -public: - LLCoordWindow() : LLCoord() - {} - LLCoordWindow(S32 x, S32 y) : LLCoord(x, y) - {} - bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const LLCoordWindow& other) const { return !(*this == other); } -}; + typedef S32 value_t; + LLCoordCommon convertToCommon() const + { + const LLCoordGL& self = LLCoordGL::getTypedCoords(*this); + return LLCoordCommon(self.mX, self.mY); + } -// Screen coords start at left, top = 0, 0 -class LLCoordScreen : public LLCoord + void convertFromCommon(const LLCoordCommon& from) + { + LLCoordGL& self = LLCoordGL::getTypedCoords(*this); + self.mX = from.mX; + self.mY = from.mY; + } +}; + +struct LL_COORD_TYPE_WINDOW { -public: - LLCoordScreen() : LLCoord() - {} - LLCoordScreen(S32 x, S32 y) : LLCoord(x, y) - {} - bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const LLCoordScreen& other) const { return !(*this == other); } + typedef S32 value_t; + + LLCoordCommon convertToCommon() const; + void convertFromCommon(const LLCoordCommon& from); }; -class LLCoordFont : public LLCoord +struct LL_COORD_TYPE_SCREEN { -public: - F32 mZ; - - LLCoordFont() : LLCoord(), mZ(0.f) - {} - LLCoordFont(S32 x, S32 y, F32 z = 0) : LLCoord(x,y), mZ(z) - {} - - void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; } - void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; } - bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const LLCoordFont& other) const { return !(*this == other); } + typedef S32 value_t; + + LLCoordCommon convertToCommon() const; + void convertFromCommon(const LLCoordCommon& from); }; - #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/llvolume.cpp b/indra/llmath/llvolume.cpp index 761fc171c4..cc9744756f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2904,7 +2904,7 @@ F32 LLVolume::sculptGetSurfaceArea() // compute the area of the quad by taking the length of the cross product of the two triangles LLVector3 cross1 = (p1 - p2) % (p1 - p3); LLVector3 cross2 = (p4 - p2) % (p4 - p3); - area += (cross1.magVec() + cross2.magVec()) / 2.0; + area += (cross1.magVec() + cross2.magVec()) / 2.f; } } @@ -5890,7 +5890,7 @@ F32 find_vertex_score(LLVCacheVertexData& data) } //bonus points for having low valence - F32 valence_boost = powf(data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); + F32 valence_boost = powf((F32)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); score += FindVertexScore_ValenceBoostScale * valence_boost; return score; diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index bad4deb4de..6a1b4143cf 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -858,25 +858,25 @@ LLSD LLMatrix4::getValue() const void LLMatrix4::setValue(const LLSD& data) { - mMatrix[0][0] = data[0].asReal(); - mMatrix[0][1] = data[1].asReal(); - mMatrix[0][2] = data[2].asReal(); - mMatrix[0][3] = data[3].asReal(); - - mMatrix[1][0] = data[4].asReal(); - mMatrix[1][1] = data[5].asReal(); - mMatrix[1][2] = data[6].asReal(); - mMatrix[1][3] = data[7].asReal(); - - mMatrix[2][0] = data[8].asReal(); - mMatrix[2][1] = data[9].asReal(); - mMatrix[2][2] = data[10].asReal(); - mMatrix[2][3] = data[11].asReal(); - - mMatrix[3][0] = data[12].asReal(); - mMatrix[3][1] = data[13].asReal(); - mMatrix[3][2] = data[14].asReal(); - mMatrix[3][3] = data[15].asReal(); + mMatrix[0][0] = (F32)data[0].asReal(); + mMatrix[0][1] = (F32)data[1].asReal(); + mMatrix[0][2] = (F32)data[2].asReal(); + mMatrix[0][3] = (F32)data[3].asReal(); + + mMatrix[1][0] = (F32)data[4].asReal(); + mMatrix[1][1] = (F32)data[5].asReal(); + mMatrix[1][2] = (F32)data[6].asReal(); + mMatrix[1][3] = (F32)data[7].asReal(); + + mMatrix[2][0] = (F32)data[8].asReal(); + mMatrix[2][1] = (F32)data[9].asReal(); + mMatrix[2][2] = (F32)data[10].asReal(); + mMatrix[2][3] = (F32)data[11].asReal(); + + mMatrix[3][0] = (F32)data[12].asReal(); + mMatrix[3][1] = (F32)data[13].asReal(); + mMatrix[3][2] = (F32)data[14].asReal(); + mMatrix[3][3] = (F32)data[15].asReal(); } diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 3bcaffc275..5ea9b58300 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -271,10 +271,10 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle) if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES) { - sFreeHandles.insert(handle); - } - else - { + sFreeHandles.insert(handle); + } + else + { LLCurl::deleteEasyHandle(handle) ; } } @@ -453,9 +453,9 @@ size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data) LLCurl::Easy* easy = (LLCurl::Easy*)user_data; S32 n = size * nmemb; - S32 startpos = easy->getInput().tellg(); + S32 startpos = (S32)easy->getInput().tellg(); easy->getInput().seekg(0, std::ios::end); - S32 endpos = easy->getInput().tellg(); + S32 endpos = (S32)easy->getInput().tellg(); easy->getInput().seekg(startpos, std::ios::beg); S32 maxn = endpos - startpos; n = llmin(n, maxn); @@ -548,6 +548,7 @@ LLCurl::Multi::Multi(F32 idle_time_out) mErrorCount(0), mState(STATE_READY), mDead(FALSE), + mValid(TRUE), mMutexp(NULL), mDeletionMutexp(NULL), mEasyMutexp(NULL) @@ -560,16 +561,16 @@ LLCurl::Multi::Multi(F32 idle_time_out) } //llassert_always(mCurlMultiHandle); - + if(mCurlMultiHandle) { - if(LLCurl::getCurlThread()->getThreaded()) - { - mMutexp = new LLMutex(NULL) ; - mDeletionMutexp = new LLMutex(NULL) ; - mEasyMutexp = new LLMutex(NULL) ; - } - LLCurl::getCurlThread()->addMulti(this) ; + if(LLCurl::getCurlThread()->getThreaded()) + { + mMutexp = new LLMutex(NULL) ; + mDeletionMutexp = new LLMutex(NULL) ; + mEasyMutexp = new LLMutex(NULL) ; + } + LLCurl::getCurlThread()->addMulti(this) ; mIdleTimeOut = idle_time_out ; if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut) @@ -577,28 +578,39 @@ LLCurl::Multi::Multi(F32 idle_time_out) mIdleTimeOut = LLCurl::sCurlRequestTimeOut ; } - ++gCurlMultiCount; - } + ++gCurlMultiCount; +} } LLCurl::Multi::~Multi() { - cleanup() ; + cleanup(true) ; + + delete mDeletionMutexp ; + mDeletionMutexp = NULL ; } -void LLCurl::Multi::cleanup() +void LLCurl::Multi::cleanup(bool deleted) { if(!mCurlMultiHandle) { return ; //nothing to clean. } + llassert_always(deleted || !mValid) ; + LLMutexLock lock(mDeletionMutexp); + // Clean up active for(easy_active_list_t::iterator iter = mEasyActiveList.begin(); iter != mEasyActiveList.end(); ++iter) { Easy* easy = *iter; check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); + + if(deleted) + { + easy->mResponder = NULL ; //avoid triggering mResponder. + } delete easy; } mEasyActiveList.clear(); @@ -610,14 +622,12 @@ void LLCurl::Multi::cleanup() check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle)); mCurlMultiHandle = NULL ; - + delete mMutexp ; mMutexp = NULL ; - delete mDeletionMutexp ; - mDeletionMutexp = NULL ; delete mEasyMutexp ; mEasyMutexp = NULL ; - + mQueued = 0 ; mState = STATE_COMPLETED; @@ -644,10 +654,20 @@ void LLCurl::Multi::unlock() void LLCurl::Multi::markDead() { - LLMutexLock lock(mDeletionMutexp) ; + { + LLMutexLock lock(mDeletionMutexp) ; - mDead = TRUE ; - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; + if(mCurlMultiHandle != NULL) + { + mDead = TRUE ; + LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; + + return; + } + } + + //not valid, delete it. + delete this; } void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) @@ -738,13 +758,17 @@ bool LLCurl::Multi::doPerform() } mQueued = q; - setState(STATE_COMPLETED) ; + setState(STATE_COMPLETED) ; mIdleTimer.reset() ; } - else if(mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. + else if(!mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. { dead = true ; } + else if(mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut - 1.f) //idle for too long, mark it invalid. + { + mValid = FALSE ; + } return dead ; } @@ -911,8 +935,8 @@ bool LLCurlThread::CurlRequest::processRequest() if(!completed) { - setPriority(LLQueuedThread::PRIORITY_LOW) ; - } + setPriority(LLQueuedThread::PRIORITY_LOW) ; + } } return completed ; @@ -922,7 +946,7 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed) { if(mMulti->isDead()) { - mCurlThread->deleteMulti(mMulti) ; + mCurlThread->deleteMulti(mMulti) ; } else { @@ -966,14 +990,7 @@ void LLCurlThread::killMulti(LLCurl::Multi* multi) return ; } - if(multi->isValid()) - { - multi->markDead() ; - } - else - { - deleteMulti(multi) ; - } + multi->markDead() ; } //private @@ -992,6 +1009,10 @@ void LLCurlThread::deleteMulti(LLCurl::Multi* multi) void LLCurlThread::cleanupMulti(LLCurl::Multi* multi) { multi->cleanup() ; + if(multi->isDead()) //check if marked dead during cleaning up. + { + deleteMulti(multi) ; + } } //------------------------------------------------------------ @@ -1033,7 +1054,7 @@ void LLCurlRequest::addMulti() mActiveRequestCount = 0 ; return; } - + mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -1229,15 +1250,15 @@ LLCurlEasyRequest::LLCurlEasyRequest() if(mMulti->isValid()) { - mEasy = mMulti->allocEasy(); - if (mEasy) - { - mEasy->setErrorBuffer(); - mEasy->setCA(); - // Set proxy settings if configured to do so. - LLProxy::getInstance()->applyProxySettings(mEasy); - } + mEasy = mMulti->allocEasy(); + if (mEasy) + { + mEasy->setErrorBuffer(); + mEasy->setCA(); + // Set proxy settings if configured to do so. + LLProxy::getInstance()->applyProxySettings(mEasy); } +} else { LLCurl::getCurlThread()->killMulti(mMulti) ; @@ -1506,7 +1527,8 @@ void LLCurl::cleanupClass() delete sHandleMutexp ; sHandleMutexp = NULL ; - llassert(Easy::sActiveHandles.empty()); + // removed as per https://jira.secondlife.com/browse/SH-3115 + //llassert(Easy::sActiveHandles.empty()); } //static diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index fd664c0fa1..d6a7714d4c 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -304,7 +304,7 @@ public: ePerformState getState() ; bool isCompleted() ; - bool isValid() {return mCurlMultiHandle != NULL ;} + bool isValid() {return mCurlMultiHandle != NULL && mValid;} bool isDead() {return mDead;} bool waitToComplete() ; @@ -318,7 +318,7 @@ public: private: void easyFree(LLCurl::Easy*); - void cleanup() ; + void cleanup(bool deleted = false) ; CURLM* mCurlMultiHandle; @@ -333,6 +333,7 @@ private: ePerformState mState; BOOL mDead ; + BOOL mValid ; LLMutex* mMutexp ; LLMutex* mDeletionMutexp ; LLMutex* mEasyMutexp ; diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 231cb7ca8f..0c325a68aa 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -158,7 +158,7 @@ namespace if(fstream.is_open()) { fstream.seekg(0, std::ios::end); - U32 fileSize = fstream.tellg(); + U32 fileSize = (U32)fstream.tellg(); fstream.seekg(0, std::ios::beg); std::vector<char> fileBuffer(fileSize); fstream.read(&fileBuffer[0], fileSize); diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp index 943a734927..9d9c4ebd68 100644 --- a/indra/llmessage/llmime.cpp +++ b/indra/llmessage/llmime.cpp @@ -388,7 +388,7 @@ bool LLMimeParser::Impl::parseHeaders( // not to read past limit when we get() the newline. S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1); istr.getline(mBuffer, max_get, '\r'); - mScanCount += istr.gcount(); + mScanCount += (S32)istr.gcount(); int c = istr.get(); if(EOF == c) { @@ -496,7 +496,7 @@ void LLMimeParser::Impl::scanPastSeparator( // past limit when we get() the newline. S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1); istr.getline(mBuffer, max_get, '\r'); - mScanCount += istr.gcount(); + mScanCount += (S32)istr.gcount(); if(istr.gcount() >= LINE_BUFFER_LENGTH - 1) { // that's way too long to be a separator, so ignore it. diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp index 9148c9dd15..1c93c12d99 100644 --- a/indra/llmessage/llsdmessage.cpp +++ b/indra/llmessage/llsdmessage.cpp @@ -88,7 +88,7 @@ bool LLSDMessage::httpListener(const LLSD& request) request, url, "POST", reply, error), LLSD(), // headers - timeout); + (F32)timeout); return false; } diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp index 2698a271ee..615221e0ad 100644 --- a/indra/llmessage/llsdmessagebuilder.cpp +++ b/indra/llmessage/llsdmessagebuilder.cpp @@ -317,7 +317,7 @@ void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data) // S64 not supported in LLSD so we just truncate it case MVT_S64: - addS32(varname, *(S64*)mvci.getData()); + addS32(varname, (S32)*(S64*)mvci.getData()); break; case MVT_F32: diff --git a/indra/llmessage/llxfer.h b/indra/llmessage/llxfer.h index 989e8b2cab..f9348eb11f 100644 --- a/indra/llmessage/llxfer.h +++ b/indra/llmessage/llxfer.h @@ -29,6 +29,7 @@ #include "message.h" #include "lltimer.h" +#include "llextendedstatus.h" const S32 LL_XFER_LARGE_PAYLOAD = 7680; diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index d0b0e178b8..6a425cfe98 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -3147,7 +3147,7 @@ bool LLMessageSystem::generateDigestForWindowAndUUIDs(char* digest, const S32 wi LL_ERRS("Messaging") << "Trying to generate complex digest on a machine without a shared secret!" << llendl; } - U32 now = time(NULL); + U32 now = (U32)time(NULL); now /= window; @@ -3167,7 +3167,7 @@ bool LLMessageSystem::isMatchingDigestForWindowAndUUIDs(const char* digest, cons } char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ - U32 now = time(NULL); + U32 now = (U32)time(NULL); now /= window; @@ -3213,7 +3213,7 @@ bool LLMessageSystem::generateDigestForWindow(char* digest, const S32 window) co LL_ERRS("Messaging") << "Trying to generate simple digest on a machine without a shared secret!" << llendl; } - U32 now = time(NULL); + U32 now = (U32)time(NULL); now /= window; diff --git a/indra/llmessage/tests/llsdmessage_test.cpp b/indra/llmessage/tests/llsdmessage_test.cpp index 0f2c069303..6871ac0d52 100644 --- a/indra/llmessage/tests/llsdmessage_test.cpp +++ b/indra/llmessage/tests/llsdmessage_test.cpp @@ -42,6 +42,7 @@ // external library headers // other Linden headers #include "../test/lltut.h" +#include "../test/catch_and_store_what_in.h" #include "llsdserialize.h" #include "llevents.h" #include "stringize.h" @@ -72,43 +73,14 @@ namespace tut template<> template<> void llsdmessage_object::test<1>() { - bool threw = false; + std::string threw; // This should fail... try { LLSDMessage localListener; } - catch (const LLEventPump::DupPumpName&) - { - threw = true; - } - catch (const std::runtime_error& ex) - { - // This clause is because on Linux, on the viewer side, for this - // one test program (though not others!), the - // LLEventPump::DupPumpName exception isn't caught by the clause - // above. Warn the user... - std::cerr << "Failed to catch " << typeid(ex).name() << std::endl; - // But if the expected exception was thrown, allow the test to - // succeed anyway. Not sure how else to handle this odd case. - if (std::string(typeid(ex).name()) == typeid(LLEventPump::DupPumpName).name()) - { - threw = true; - } - else - { - // We don't even recognize this exception. Let it propagate - // out to TUT to fail the test. - throw; - } - } - catch (...) - { - std::cerr << "Utterly failed to catch expected exception!" << std::endl; - // This case is full of fail. We HAVE to address it. - throw; - } - ensure("second LLSDMessage should throw", threw); + CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName) + ensure("second LLSDMessage should throw", ! threw.empty()); } template<> template<> diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py index f2c841532a..5b9beb359b 100644 --- a/indra/llmessage/tests/testrunner.py +++ b/indra/llmessage/tests/testrunner.py @@ -35,7 +35,7 @@ import re import errno import socket -VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "1") # default to verbose +VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "0") # default to quiet # Support usage such as INTEGRATION_TEST_VERBOSE=off -- distressing to user if # that construct actually turns on verbosity... VERBOSE = not re.match(r"(0|off|false|quiet)$", VERBOSE, re.IGNORECASE) diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 110fac0f23..f10eaee5b4 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -31,6 +31,7 @@ #include "llpluginprocessparent.h" #include "llpluginmessagepipe.h" #include "llpluginmessageclasses.h" +#include "stringize.h" #include "llapr.h" @@ -134,7 +135,10 @@ LLPluginProcessParent::~LLPluginProcessParent() mSharedMemoryRegions.erase(iter); } - mProcess.kill(); + if (mProcess) + { + mProcess->kill(); + } killSockets(); } @@ -159,8 +163,8 @@ void LLPluginProcessParent::errorState(void) void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug) { - mProcess.setExecutable(launcher_filename); - mProcess.setWorkingDirectory(plugin_dir); + mProcessParams.executable = launcher_filename; + mProcessParams.cwd = plugin_dir; mPluginFile = plugin_filename; mPluginDir = plugin_dir; mCPUUsage = 0.0f; @@ -371,10 +375,8 @@ void LLPluginProcessParent::idle(void) // Launch the plugin process. // Only argument to the launcher is the port number we're listening on - std::stringstream stream; - stream << mBoundPort; - mProcess.addArgument(stream.str()); - if(mProcess.launch() != 0) + mProcessParams.args.add(stringize(mBoundPort)); + if (! (mProcess = LLProcess::create(mProcessParams))) { errorState(); } @@ -388,19 +390,18 @@ void LLPluginProcessParent::idle(void) // The command we're constructing would look like this on the command line: // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell' - std::stringstream cmd; - - mDebugger.setExecutable("/usr/bin/osascript"); - mDebugger.addArgument("-e"); - mDebugger.addArgument("tell application \"Terminal\""); - mDebugger.addArgument("-e"); - cmd << "set win to do script \"gdb -pid " << mProcess.getProcessID() << "\""; - mDebugger.addArgument(cmd.str()); - mDebugger.addArgument("-e"); - mDebugger.addArgument("do script \"continue\" in win"); - mDebugger.addArgument("-e"); - mDebugger.addArgument("end tell"); - mDebugger.launch(); + LLProcess::Params params; + params.executable = "/usr/bin/osascript"; + params.args.add("-e"); + params.args.add("tell application \"Terminal\""); + params.args.add("-e"); + params.args.add(STRINGIZE("set win to do script \"gdb -pid " + << mProcess->getProcessID() << "\"")); + params.args.add("-e"); + params.args.add("do script \"continue\" in win"); + params.args.add("-e"); + params.args.add("end tell"); + mDebugger = LLProcess::create(params); #endif } @@ -470,7 +471,7 @@ void LLPluginProcessParent::idle(void) break; case STATE_EXITING: - if(!mProcess.isRunning()) + if (! mProcess->isRunning()) { setState(STATE_CLEANUP); } @@ -498,7 +499,7 @@ void LLPluginProcessParent::idle(void) break; case STATE_CLEANUP: - mProcess.kill(); + mProcess->kill(); killSockets(); setState(STATE_DONE); break; @@ -1077,7 +1078,7 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit() { bool result = false; - if(!mProcess.isRunning()) + if (! mProcess->isRunning()) { LL_WARNS("Plugin") << "child exited" << LL_ENDL; result = true; diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index c66723f175..990fc5cbae 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -30,13 +30,14 @@ #define LL_LLPLUGINPROCESSPARENT_H #include "llapr.h" -#include "llprocesslauncher.h" +#include "llprocess.h" #include "llpluginmessage.h" #include "llpluginmessagepipe.h" #include "llpluginsharedmemory.h" #include "lliosocket.h" #include "llthread.h" +#include "llsd.h" class LLPluginProcessParentOwner { @@ -139,26 +140,27 @@ private: }; EState mState; void setState(EState state); - + bool pluginLockedUp(); bool pluginLockedUpOrQuit(); bool accept(); - + LLSocket::ptr_t mListenSocket; LLSocket::ptr_t mSocket; U32 mBoundPort; - - LLProcessLauncher mProcess; - + + LLProcess::Params mProcessParams; + LLProcessPtr mProcess; + std::string mPluginFile; std::string mPluginDir; LLPluginProcessParentOwner *mOwner; - + typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType; sharedMemoryRegionsType mSharedMemoryRegions; - + LLSD mMessageClassVersions; std::string mPluginVersionString; @@ -171,7 +173,7 @@ private: bool mBlocked; bool mPolledInput; - LLProcessLauncher mDebugger; + LLProcessPtr mDebugger; F32 mPluginLaunchTimeout; // Somewhat longer timeout for initial launch. F32 mPluginLockupTimeout; // If we don't receive a heartbeat in this many seconds, we declare the plugin locked up. diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 82e8227ffe..fccbf37a8d 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -56,8 +56,9 @@ std::string LLFontGL::sAppDir; LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f); LLFontRegistry* LLFontGL::sFontRegistry = NULL; -LLCoordFont LLFontGL::sCurOrigin; -std::vector<LLCoordFont> LLFontGL::sOriginStack; +LLCoordGL LLFontGL::sCurOrigin; +F32 LLFontGL::sCurDepth; +std::vector<std::pair<LLCoordGL, F32> > LLFontGL::sOriginStack; const F32 EXT_X_BEARING = 1.f; const F32 EXT_Y_BEARING = 0.f; @@ -68,20 +69,6 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; -static F32 llfont_round_x(F32 x) -{ - //return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX; - //return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY; - return x; -} - -static F32 llfont_round_y(F32 y) -{ - //return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY; - //return llfloor(y+0.5f); - return y; -} - LLFontGL::LLFontGL() { } @@ -115,23 +102,23 @@ static LLFastTimer::DeclareTimer FTM_RENDER_FONTS("Fonts"); S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const { - F32 x = rect.mLeft; + F32 x = (F32)rect.mLeft; F32 y = 0.f; switch(valign) { case TOP: - y = rect.mTop; + y = (F32)rect.mTop; break; case VCENTER: - y = rect.getCenterY(); + y = (F32)rect.getCenterY(); break; case BASELINE: case BOTTOM: - y = rect.mBottom; + y = (F32)rect.mBottom; break; default: - y = rect.mBottom; + y = (F32)rect.mBottom; break; } return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses); @@ -177,21 +164,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons gGL.loadUIIdentity(); - //gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); - - // this code snaps the text origin to a pixel grid to start with - //F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); - //F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); - //gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f); - LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY)); - // snap the text origin to a pixel grid to start with - origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); - origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); - // Depth translation, so that floating text appears 'inworld' - // and is correclty occluded. - gGL.translatef(0.f,0.f,sCurOrigin.mZ); + // Depth translation, so that floating text appears 'in-world' + // and is correctly occluded. + gGL.translatef(0.f,0.f,sCurDepth); S32 chars_drawn = 0; S32 i; @@ -215,16 +192,17 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_y = ((F32)y * sScaleY) + origin.mV[VY]; // Offset y by vertical alignment. + // use unscaled font metrics here switch (valign) { case TOP: - cur_y -= mFontFreetype->getAscenderHeight(); + cur_y -= llceil(mFontFreetype->getAscenderHeight()); break; case BOTTOM: - cur_y += mFontFreetype->getDescenderHeight(); + cur_y += llceil(mFontFreetype->getDescenderHeight()); break; case VCENTER: - cur_y -= (mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight()) / 2.f; + cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) - llceil(mFontFreetype->getDescenderHeight())) / 2.f); break; case BASELINE: // Baseline, do nothing. @@ -250,7 +228,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_render_y = cur_y; cur_render_x = cur_x; - F32 start_x = llround(cur_x); + F32 start_x = (F32)llround(cur_x); const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); @@ -334,10 +312,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons (fgi->mXBitmapOffset + fgi->mWidth) * inv_width, (fgi->mYBitmapOffset - PAD_UVY) * inv_height); // snap glyph origin to whole screen pixel - LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing), - llround(cur_render_y + (F32)fgi->mYBearing), - llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, - llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); + LLRectf screen_rect((F32)llround(cur_render_x + (F32)fgi->mXBearing), + (F32)llround(cur_render_y + (F32)fgi->mYBearing), + (F32)llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, + (F32)llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); if (glyph_count >= GLYPH_BATCH_SIZE) { @@ -390,12 +368,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons //FIXME: add underline as glyph? if (style_to_add & UNDERLINE) { - F32 descender = mFontFreetype->getDescenderHeight(); + F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight()); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.begin(LLRender::LINES); - gGL.vertex2f(start_x, cur_y - (descender)); - gGL.vertex2f(cur_x, cur_y - (descender)); + gGL.vertex2f(start_x, cur_y - descender); + gGL.vertex2f(cur_x, cur_y - descender); gGL.end(); } @@ -444,19 +422,9 @@ 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::getLineHeight() const +S32 LLFontGL::getLineHeight() const { - return (F32)llround(mFontFreetype->getLineHeight() / sScaleY); -} - -F32 LLFontGL::getAscenderHeight() const -{ - return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY); -} - -F32 LLFontGL::getDescenderHeight() const -{ - return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY); + return llceil(mFontFreetype->getAscenderHeight() / sScaleY) + llceil(mFontFreetype->getDescenderHeight() / sScaleY); } S32 LLFontGL::getWidth(const std::string& utf8text) const @@ -645,7 +613,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch } // Round after kerning. - cur_x = llround(cur_x); + cur_x = (F32)llround(cur_x); drawn_x = cur_x; } @@ -716,7 +684,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ } // Round after kerning. - total_width = llround(total_width); + total_width = (F32)llround(total_width); } if (drawable_chars == 0) @@ -799,7 +767,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t // Round after kerning. - cur_x = llround(cur_x); + cur_x = (F32)llround(cur_x); } return llmin(max_chars, pos - begin_offset); @@ -1146,22 +1114,22 @@ void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* c { S32 index = 0; - vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mTop), 0.f); + vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f); uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mTop), 0.f); + vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f); uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mBottom), 0.f); + vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f); uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mBottom), 0.f); + vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f); uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); colors_out[index] = color; } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index dc8d848ed2..74bdbb43e7 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -115,9 +115,7 @@ 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 getLineHeight() const; - F32 getAscenderHeight() const; - F32 getDescenderHeight() const; + S32 getLineHeight() const; S32 getWidth(const std::string& utf8text) const; S32 getWidth(const llwchar* wchars) const; @@ -188,8 +186,9 @@ public: static std::string getFontPathLocal(); static std::string getFontPathSystem(); - static LLCoordFont sCurOrigin; - static std::vector<LLCoordFont> sOriginStack; + static LLCoordGL sCurOrigin; + static F32 sCurDepth; + static std::vector<std::pair<LLCoordGL, F32> > sOriginStack; static LLColor4 sShadowColor; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 946e602fee..628a8d6131 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -94,9 +94,15 @@ void APIENTRY gl_debug_callback(GLenum source, llwarns << "Severity: " << std::hex << severity << llendl; llwarns << "Message: " << message << llendl; llwarns << "-----------------------" << llendl; + if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) + { + llerrs << "Halting on GL Error" << llendl; + } } #endif +void parse_glsl_version(S32& major, S32& minor); + void ll_init_fail_log(std::string filename) { gFailLog.open(filename.c_str()); @@ -295,6 +301,7 @@ PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB = NULL; PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB = NULL; PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL; PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL; +PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL; #if LL_WINDOWS PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; @@ -443,7 +450,8 @@ LLGLManager::LLGLManager() : mDriverVersionMinor(0), mDriverVersionRelease(0), mGLVersion(1.0f), - + mGLSLVersionMajor(0), + mGLSLVersionMinor(0), mVRAM(0), mGLMaxVertexRange(0), mGLMaxIndexRange(0) @@ -554,6 +562,29 @@ bool LLGLManager::initGL() mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f; + if (mGLVersion >= 2.f) + { + parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor); + +#if LL_DARWIN + //never use GLSL greater than 1.20 on OSX + if (mGLSLVersionMajor > 1 || mGLSLVersionMinor >= 30) + { + mGLSLVersionMajor = 1; + mGLSLVersionMinor = 20; + } +#endif + } + + if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures) + { //use texture compression + glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); + } + else + { //GL version is < 3.0, always disable texture compression + LLImageGL::sCompressTextures = false; + } + // Trailing space necessary to keep "nVidia Corpor_ati_on" cards // from being recognized as ATI. if (mGLVendor.substr(0,4) == "ATI ") @@ -574,11 +605,8 @@ bool LLGLManager::initGL() #endif // LL_WINDOWS #if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS - // release 7277 is a point at which we verify that ATI OpenGL - // drivers get pretty stable with SL, ~Catalyst 8.2, - // for both Win32 and Linux. - if (mDriverVersionRelease < 7277 && - mDriverVersionRelease != 0) // 0 == Undetectable driver version - these get to pretend to be new ATI drivers, though that decision may be revisited. + // count any pre OpenGL 3.0 implementation as an old driver + if (mGLVersion < 3.f) { mATIOldDriver = TRUE; } @@ -717,6 +745,11 @@ bool LLGLManager::initGL() } #endif + if (mIsIntel && mGLVersion <= 3.f) + { //never try to use framebuffer objects on older intel drivers (crashy) + mHasFramebufferObject = FALSE; + } + if (mHasFramebufferObject) { glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); @@ -1300,6 +1333,7 @@ void LLGLManager::initExtensions() glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB"); glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB"); glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB"); + glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer"); glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB"); glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB"); glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB"); @@ -1878,7 +1912,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); - if (gGLManager.mHasVertexShader) + if (gGLManager.mHasVertexShader && LLGLSLShader::sNoFixedFunction) { //make sure vertex attribs are all disabled GLint count; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &count); @@ -2098,6 +2132,55 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor } } + +void parse_glsl_version(S32& major, S32& minor) +{ + // GL_SHADING_LANGUAGE_VERSION returns a null-terminated string with the format: + // <major>.<minor>[.<release>] [<vendor specific>] + + const char* version = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); + major = 0; + minor = 0; + + if( !version ) + { + return; + } + + std::string ver_copy( version ); + S32 len = (S32)strlen( version ); /* Flawfinder: ignore */ + S32 i = 0; + S32 start; + // Find the major version + start = i; + for( ; i < len; i++ ) + { + if( '.' == version[i] ) + { + break; + } + } + std::string major_str = ver_copy.substr(start,i-start); + LLStringUtil::convertToS32(major_str, major); + + if( '.' == version[i] ) + { + i++; + } + + // Find the minor version + start = i; + for( ; i < len; i++ ) + { + if( ('.' == version[i]) || isspace(version[i]) ) + { + break; + } + } + std::string minor_str = ver_copy.substr(start,i-start); + LLStringUtil::convertToS32(minor_str, minor); +} + LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply) { mApply = apply; diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 6a147b8e19..5a33c98708 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -138,6 +138,8 @@ public: S32 mDriverVersionMinor; S32 mDriverVersionRelease; F32 mGLVersion; // e.g = 1.4 + S32 mGLSLVersionMajor; + S32 mGLSLVersionMinor; std::string mDriverVersionVendorString; S32 mVRAM; // VRAM in MB diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 10aad202e1..d61ec707f0 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -199,6 +199,7 @@ extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB; extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB; extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB; extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB; +extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB; extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB; extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB; @@ -460,6 +461,7 @@ extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB; extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB; extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB; extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB; +extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB; extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB; extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB; @@ -693,6 +695,7 @@ extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB; extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB; extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB; extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB; +extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB; extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB; extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 6b2852670a..4b7e639aed 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -64,10 +64,23 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) } LLShaderFeatures::LLShaderFeatures() -: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), -hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false), -hasGamma(false), hasLighting(false), isAlphaLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false), -hasAlphaMask(false) + : atmosphericHelpers(false) + , calculatesLighting(false) + , calculatesAtmospherics(false) + , hasLighting(false) + , isAlphaLighting(false) + , isShiny(false) + , isFullbright(false) + , isSpecular(false) + , hasWaterFog(false) + , hasTransport(false) + , hasSkinning(false) + , hasObjectSkinning(false) + , hasAtmospherics(false) + , hasGamma(false) + , mIndexedTextureChannels(0) + , disableTextureIndex(false) + , hasAlphaMask(false) { } @@ -96,7 +109,12 @@ void LLGLSLShader::unload() glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj); for (GLsizei i = 0; i < count; i++) { - glDeleteObjectARB(obj[i]); +#if !LL_DARWIN + if (glIsProgramARB(obj[i])) +#endif + { + glDeleteObjectARB(obj[i]); + } } glDeleteObjectARB(mProgramObject); @@ -148,8 +166,9 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, return FALSE; } - if (gGLManager.mGLVersion < 3.1f) - { //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again + if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 3) + { //indexed texture rendering requires GLSL 1.3 or later + //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 00b4b0dbd4..7873fe3c4e 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -33,6 +33,7 @@ class LLShaderFeatures { public: + bool atmosphericHelpers; bool calculatesLighting; bool calculatesAtmospherics; bool hasLighting; // implies no transport (it's possible to have neither though) diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 78591ddd38..c04a3f6b41 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -43,7 +43,6 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f; //statics -LLGLuint LLImageGL::sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS] = { 0 }; U32 LLImageGL::sUniqueCount = 0; U32 LLImageGL::sBindCount = 0; @@ -57,6 +56,7 @@ BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; BOOL LLImageGL::sAllowReadBackRaw = FALSE ; LLImageGL* LLImageGL::sDefaultGLTexture = NULL ; +bool LLImageGL::sCompressTextures = false; std::set<LLImageGL*> LLImageGL::sImageList; @@ -65,19 +65,10 @@ std::set<LLImageGL*> LLImageGL::sImageList; //**************************************************************************************************** //----------------------- //debug use -BOOL gAuditTexture = FALSE ; -#define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048 -std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ; -std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; -std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; S32 LLImageGL::sCurTexSizeBar = -1 ; S32 LLImageGL::sCurTexPickSize = -1 ; -LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL; -S32 LLImageGL::sMaxCatagories = 1 ; +S32 LLImageGL::sMaxCategories = 1 ; -std::vector<S32> LLImageGL::sTextureMemByCategory; -std::vector<S32> LLImageGL::sTextureMemByCategoryBound ; -std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ; //------------------------ //**************************************************************************************************** //End for texture auditing use only @@ -175,49 +166,11 @@ BOOL is_little_endian() //static void LLImageGL::initClass(S32 num_catagories) { - sMaxCatagories = num_catagories ; - - sTextureMemByCategory.resize(sMaxCatagories); - sTextureMemByCategoryBound.resize(sMaxCatagories) ; - sTextureCurMemByCategoryBound.resize(sMaxCatagories) ; } //static void LLImageGL::cleanupClass() { - sTextureMemByCategory.clear() ; - sTextureMemByCategoryBound.clear() ; - sTextureCurMemByCategoryBound.clear() ; -} - -//static -void LLImageGL::setHighlightTexture(S32 category) -{ - const S32 dim = 128; - sHighlightTexturep = new LLImageGL() ; - LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3); - U8* data = image_raw->getData(); - for (S32 i = 0; i<dim; i++) - { - for (S32 j = 0; j<dim; j++) - { - const S32 border = 2; - if (i<border || j<border || i>=(dim-border) || j>=(dim-border)) - { - *data++ = 0xff; - *data++ = 0xff; - *data++ = 0xff; - } - else - { - *data++ = 0xff; - *data++ = 0xff; - *data++ = 0x00; - } - } - } - sHighlightTexturep->createGLTexture(0, image_raw, 0, TRUE, category); - image_raw = NULL; } //static @@ -285,31 +238,11 @@ void LLImageGL::updateStats(F32 current_time) sLastFrameTime = current_time; sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; - - if(gAuditTexture) - { - for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) - { - sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; - sTextureCurBoundCounter[i] = 0 ; - } - for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++) - { - sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ; - sTextureCurMemByCategoryBound[i] = 0 ; - } - } } //static S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) { - if(gAuditTexture && ncomponents > 0 && category > -1) - { - sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ; - sTextureCurMemByCategoryBound[category] += mem ; - } - LLImageGL::sCurBoundTextureMemory += mem ; return LLImageGL::sCurBoundTextureMemory; } @@ -477,6 +410,8 @@ void LLImageGL::init(BOOL usemipmaps) mDiscardLevelInAtlas = -1 ; mTexelsInAtlas = 0 ; mTexelsInGLTexture = 0 ; + + mAllowCompression = true; mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; @@ -705,7 +640,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } - LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in); + LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in, mAllowCompression); if (gl_level == 0) { analyzeAlpha(data_in, w, h); @@ -747,7 +682,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, - data_in); + data_in, mAllowCompression); analyzeAlpha(data_in, w, h); stop_glerror(); @@ -805,7 +740,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } - LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data); + LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); if (m == 0) { analyzeAlpha(data_in, w, h); @@ -863,7 +798,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, - mFormatPrimary, mFormatType, (GLvoid *)data_in); + mFormatPrimary, mFormatType, (GLvoid *)data_in, mAllowCompression); analyzeAlpha(data_in, w, h); updatePickMask(w, h, data_in); @@ -1110,7 +1045,7 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate) } // static -void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels) +void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression) { bool use_scratch = false; U32* scratch = NULL; @@ -1173,6 +1108,36 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } } + if (LLImageGL::sCompressTextures && allow_compression) + { + switch (intformat) + { + case GL_RGB: + case GL_RGB8: + intformat = GL_COMPRESSED_RGB; + break; + case GL_RGBA: + case GL_RGBA8: + intformat = GL_COMPRESSED_RGBA; + break; + case GL_LUMINANCE: + case GL_LUMINANCE8: + intformat = GL_COMPRESSED_LUMINANCE; + break; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE8_ALPHA8: + intformat = GL_COMPRESSED_LUMINANCE_ALPHA; + break; + case GL_ALPHA: + case GL_ALPHA8: + intformat = GL_COMPRESSED_ALPHA; + break; + default: + llwarns << "Could not compress format: " << std::hex << intformat << llendl; + break; + } + } + stop_glerror(); glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); stop_glerror(); @@ -1284,7 +1249,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return TRUE ; } - setCategory(category) ; + setCategory(category); const U8* rawdata = imageraw->getData(); return createGLTexture(discard_level, rawdata, FALSE, usename); } @@ -1362,11 +1327,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ { sGlobalTextureMemoryInBytes -= mTextureMemory; - if(gAuditTexture) - { - decTextureCounter(mTextureMemory, mComponents, mCategory) ; - } - LLImageGL::deleteTextures(1, &old_name); stop_glerror(); @@ -1376,10 +1336,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ sGlobalTextureMemoryInBytes += mTextureMemory; mTexelsInGLTexture = getWidth() * getHeight() ; - if(gAuditTexture) - { - incTextureCounter(mTextureMemory, mComponents, mCategory) ; - } // mark this as bound at this point, so we don't throw it out immediately mLastBindTime = sLastFrameTime; return TRUE; @@ -1536,22 +1492,29 @@ void LLImageGL::destroyGLTexture() { if(mTextureMemory) { - if(gAuditTexture) - { - decTextureCounter(mTextureMemory, mComponents, mCategory) ; - } sGlobalTextureMemoryInBytes -= mTextureMemory; mTextureMemory = 0; } LLImageGL::deleteTextures(1, &mTexName); - mTexName = 0; mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. + mTexName = 0; mGLTextureCreated = FALSE ; - } + } } - +//force to invalidate the gl texture, most likely a sculpty texture +void LLImageGL::forceToInvalidateGLTexture() +{ + if (mTexName != 0) + { + destroyGLTexture(); + } + else + { + mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. + } +} //---------------------------------------------------------------------------- @@ -1969,70 +1932,6 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) return res; } -void LLImageGL::setCategory(S32 category) -{ -#if 0 //turn this off temporarily because it is not in use now. - if(!gAuditTexture) - { - return ; - } - if(mCategory != category) - { - if(mCategory > -1) - { - sTextureMemByCategory[mCategory] -= mTextureMemory ; - } - if(category > -1 && category < sMaxCatagories) - { - sTextureMemByCategory[category] += mTextureMemory ; - mCategory = category; - } - else - { - mCategory = -1 ; - } - } -#endif -} - -//for debug use -//val is a "power of two" number -S32 LLImageGL::getTextureCounterIndex(U32 val) -{ - //index range is [0, MAX_TEXTURE_LOG_SIZE]. - if(val < 2) - { - return 0 ; - } - else if(val >= (1 << MAX_TEXTURE_LOG_SIZE)) - { - return MAX_TEXTURE_LOG_SIZE ; - } - else - { - S32 ret = 0 ; - while(val >>= 1) - { - ++ret; - } - return ret ; - } -} - -//static -void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category) -{ - sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; - sTextureMemByCategory[category] += (S32)val * ncomponents ; -} - -//static -void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category) -{ - sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; - sTextureMemByCategory[category] += (S32)val * ncomponents ; -} - void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size) { sCurTexSizeBar = index ; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 2cfb15b0d9..f34b9fa91a 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -94,16 +94,17 @@ public: void setSize(S32 width, S32 height, S32 ncomponents); 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); + 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() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, - S32 category = sMaxCatagories - 1); + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, + S32 category = sMaxCategories-1); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); void setImage(const LLImageRaw* imageraw); void setImage(const U8* data_in, BOOL data_hasmips = FALSE); @@ -114,6 +115,7 @@ public: // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const; void destroyGLTexture(); + void forceToInvalidateGLTexture(); void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); void setComponents(S8 ncomponents) { mComponents = ncomponents; } @@ -209,6 +211,8 @@ private: U32 mTexelsInAtlas ; U32 mTexelsInGLTexture; + bool mAllowCompression; + protected: LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) @@ -234,8 +238,6 @@ public: static S32 sCount; static F32 sLastFrameTime; - - static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID // Global memory statistics static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem @@ -246,7 +248,7 @@ public: static BOOL sGlobalUseAnisotropic; static LLImageGL* sDefaultGLTexture ; static BOOL sAutomatedTest; - + static bool sCompressTextures; //use GL texture compression #if DEBUG_MISS BOOL mMissed; // Missed on last bind? BOOL getMissed() const { return mMissed; }; @@ -257,9 +259,10 @@ public: public: static void initClass(S32 num_catagories) ; static void cleanupClass() ; -private: - static S32 sMaxCatagories ; +private: + static S32 sMaxCategories; + //the flag to allow to call readBackRaw(...). //can be removed if we do not use that function at all. static BOOL sAllowReadBackRaw ; @@ -269,39 +272,22 @@ private: //**************************************************************************************************** private: S32 mCategory ; -public: - void setCategory(S32 category) ; - S32 getCategory()const {return mCategory ;} - +public: + void setCategory(S32 category) {mCategory = category;} + S32 getCategory()const {return mCategory;} + //for debug use: show texture size distribution //---------------------------------------- - static LLPointer<LLImageGL> sHighlightTexturep; //default texture to replace normal textures - static std::vector<S32> sTextureLoadedCounter ; - static std::vector<S32> sTextureBoundCounter ; - static std::vector<S32> sTextureCurBoundCounter ; static S32 sCurTexSizeBar ; static S32 sCurTexPickSize ; - static void setHighlightTexture(S32 category) ; - static S32 getTextureCounterIndex(U32 val) ; - static void incTextureCounter(U32 val, S32 ncomponents, S32 category) ; - static void decTextureCounter(U32 val, S32 ncomponents, S32 category) ; static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ; static void resetCurTexSizebar(); - //---------------------------------------- - //for debug use: show texture category distribution - //---------------------------------------- - - static std::vector<S32> sTextureMemByCategory; - static std::vector<S32> sTextureMemByCategoryBound ; - static std::vector<S32> sTextureCurMemByCategoryBound ; - //---------------------------------------- //**************************************************************************************************** //End of definitions for texture auditing use only //**************************************************************************************************** }; -extern BOOL gAuditTexture; #endif // LL_LLIMAGEGL_H diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index b0ddacbb05..93bac4c779 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -246,14 +246,6 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) } //in audit, replace the selected texture by the default one. - if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) - { - if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) - { - gl_tex->updateBindStats(gl_tex->mTextureMemory); - return bind(LLImageGL::sHighlightTexturep.get()); - } - } if ((mCurrTexture != gl_tex->getTexName()) || forceBind) { activate(); diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index ef2a7395da..780f1dc484 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -143,7 +143,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) { clear_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); if (glGetError() != GL_NO_ERROR) { llwarns << "Could not allocate color buffer for render target." << llendl; @@ -223,7 +223,7 @@ bool LLRenderTarget::allocateDepth() U32 internal_type = LLTexUnit::getInternalType(mUsage); stop_glerror(); clear_glerror(); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 1a03aeebb7..5a6e6cab3e 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -94,13 +94,16 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } - if (features->calculatesLighting) + if (features->calculatesLighting || features->atmosphericHelpers) { if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl")) { return FALSE; } + } + if (features->calculatesLighting) + { if (features->isSpecular) { if (!shader->attachObject("lighting/lightFuncSpecularV.glsl")) @@ -572,34 +575,46 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade GLcharARB* text[4096]; GLuint count = 0; - F32 version = gGLManager.mGLVersion; - -//hack to never use GLSL > 1.20 on OSX -#if LL_DARWIN - version = llmin(version, 2.9f); -#endif - - if (version < 2.1f) - { - text[count++] = strdup("#version 110\n"); - text[count++] = strdup("#define ATTRIBUTE attribute\n"); - text[count++] = strdup("#define VARYING varying\n"); - } - else if (version < 3.3f) + S32 major_version = gGLManager.mGLSLVersionMajor; + S32 minor_version = gGLManager.mGLSLVersionMinor; + + if (major_version == 1 && minor_version < 30) { - //set version to 1.20 - text[count++] = strdup("#version 120\n"); - text[count++] = strdup("#define FXAA_GLSL_120 1\n"); - text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n"); - text[count++] = strdup("#define ATTRIBUTE attribute\n"); - text[count++] = strdup("#define VARYING varying\n"); + if (minor_version < 10) + { + //should NEVER get here -- if major version is 1 and minor version is less than 10, + // viewer should never attempt to use shaders, continuing will result in undefined behavior + llerrs << "Unsupported GLSL Version." << llendl; + } + + if (minor_version <= 19) + { + text[count++] = strdup("#version 110\n"); + text[count++] = strdup("#define ATTRIBUTE attribute\n"); + text[count++] = strdup("#define VARYING varying\n"); + text[count++] = strdup("#define VARYING_FLAT varying\n"); + } + else if (minor_version <= 29) + { + //set version to 1.20 + text[count++] = strdup("#version 120\n"); + text[count++] = strdup("#define FXAA_GLSL_120 1\n"); + text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n"); + text[count++] = strdup("#define ATTRIBUTE attribute\n"); + text[count++] = strdup("#define VARYING varying\n"); + text[count++] = strdup("#define VARYING_FLAT varying\n"); + } } else { - if (version < 4.f) + if (major_version < 4) { //set version to 1.30 text[count++] = strdup("#version 130\n"); + + //some implementations of GLSL 1.30 require integer precision be explicitly declared + text[count++] = strdup("precision mediump int;\n"); + text[count++] = strdup("precision highp float;\n"); } else { //set version to 400 @@ -615,16 +630,25 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade { //"varying" state is "out" in a vertex program, "in" in a fragment program // ("varying" is deprecated after version 1.20) text[count++] = strdup("#define VARYING out\n"); + text[count++] = strdup("#define VARYING_FLAT flat out\n"); } else { text[count++] = strdup("#define VARYING in\n"); + text[count++] = strdup("#define VARYING_FLAT flat in\n"); } //backwards compatibility with legacy texture lookup syntax + text[count++] = strdup("#define texture2D texture\n"); text[count++] = strdup("#define textureCube texture\n"); text[count++] = strdup("#define texture2DLod textureLod\n"); text[count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n"); + + if (major_version > 1 || minor_version >= 40) + { //GLSL 1.40 replaces texture2DRect et al with texture + text[count++] = strdup("#define texture2DRect texture\n"); + text[count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n"); + } } //copy preprocessor definitions into buffer @@ -648,22 +672,24 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade . uniform sampler2D texN; - VARYING float vary_texture_index; + VARYING_FLAT ivec4 vary_texture_index; + + vec4 ret = vec4(1,0,1,1); vec4 diffuseLookup(vec2 texcoord) { - switch (int(vary_texture_index+0.25)) + switch (vary_texture_index.r)) { - case 0: return texture2D(tex0, texcoord); - case 1: return texture2D(tex1, texcoord); - case 2: return texture2D(tex2, texcoord); + case 0: ret = texture2D(tex0, texcoord); break; + case 1: ret = texture2D(tex1, texcoord); break; + case 2: ret = texture2D(tex2, texcoord); break; . . . - case N: return texture2D(texN, texcoord); + case N: return texture2D(texN, texcoord); break; } - return vec4(0,0,0,0); + return ret; } */ @@ -676,7 +702,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (texture_index_channels > 1) { - text[count++] = strdup("VARYING float vary_texture_index;\n"); + text[count++] = strdup("VARYING_FLAT ivec4 vary_texture_index;\n"); } text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); @@ -688,45 +714,28 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade text[count++] = strdup("return texture2D(tex0, texcoord);\n"); text[count++] = strdup("}\n"); } - else if (gGLManager.mGLVersion >= 3.f) - { - text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n"); + 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: return texture2D(tex%d, texcoord);\n", i, 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()); } text[count++] = strdup("\t}\n"); - text[count++] = strdup("\treturn vec4(1,0,1,1);\n"); + text[count++] = strdup("\treturn ret;\n"); text[count++] = strdup("}\n"); } else - { - //switches aren't supported, make block that looks like: - /* - int ti = int(vary_texture_index+0.25); - if (ti == 0) return texture2D(tex0, texcoord); - if (ti == 1) return texture2D(tex1, texcoord); - . - . - . - if (ti == N) return texture2D(texN, texcoord); - */ - - text[count++] = strdup("int ti = int(vary_texture_index+0.25);\n"); - for (S32 i = 0; i < texture_index_channels; ++i) - { - std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i); - text[count++] = strdup(if_str.c_str()); - } - - text[count++] = strdup("\treturn vec4(1,0,1,1);\n"); - text[count++] = strdup("}\n"); - } + { //should never get here. Indexed texture rendering requires GLSL 1.30 or later + // (for passing integers between vertex and fragment shaders) + llerrs << "Indexed texture rendering requires GLSL 1.30 or later." << llendl; + } } //copy file into memory @@ -1053,8 +1062,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("proj_shadow_res"); mReservedUniforms.push_back("depth_cutoff"); mReservedUniforms.push_back("norm_cutoff"); + mReservedUniforms.push_back("shadow_target_width"); - llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_NORM_CUTOFF+1); + llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1); mReservedUniforms.push_back("tc_scale"); mReservedUniforms.push_back("rcp_screen_res"); @@ -1067,6 +1077,8 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("magnification"); mReservedUniforms.push_back("max_cof"); mReservedUniforms.push_back("res_scale"); + mReservedUniforms.push_back("dof_width"); + mReservedUniforms.push_back("dof_height"); mReservedUniforms.push_back("depthMap"); mReservedUniforms.push_back("shadowMap0"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 950e6c9c2f..f792faa8f0 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -130,6 +130,7 @@ public: DEFERRED_PROJ_SHADOW_RES, DEFERRED_DEPTH_CUTOFF, DEFERRED_NORM_CUTOFF, + DEFERRED_SHADOW_TARGET_WIDTH, FXAA_TC_SCALE, FXAA_RCP_SCREEN_RES, @@ -142,6 +143,8 @@ public: DOF_MAGNIFICATION, DOF_MAX_COF, DOF_RES_SCALE, + DOF_WIDTH, + DOF_HEIGHT, DEFERRED_DEPTH, DEFERRED_SHADOW0, diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index eb302392bb..823c6b9dc5 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -38,6 +38,12 @@ #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) @@ -49,35 +55,69 @@ U32 nhpo2(U32 v) return r; } +//which power of 2 is i? +//assumes i is a power of 2 > 0 +U32 wpo2(U32 i) +{ + llassert(i > 0); + llassert(nhpo2(i) == i); + + U32 r = 0; + + while (i >>= 1) ++r; + + return r; +} + + +const U32 LL_VBO_BLOCK_SIZE = 2048; + +U32 vbo_block_size(U32 size) +{ //what block size will fit size? + U32 mod = size % LL_VBO_BLOCK_SIZE; + return mod == 0 ? size : size + (LL_VBO_BLOCK_SIZE-mod); +} + +U32 vbo_block_index(U32 size) +{ + return vbo_block_size(size)/LL_VBO_BLOCK_SIZE; +} + + //============================================================================ //static -LLVBOPool LLVertexBuffer::sStreamVBOPool; -LLVBOPool LLVertexBuffer::sDynamicVBOPool; -LLVBOPool LLVertexBuffer::sStreamIBOPool; -LLVBOPool LLVertexBuffer::sDynamicIBOPool; +LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB); +LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB); +LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB); +LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB); + U32 LLVBOPool::sBytesPooled = 0; +U32 LLVBOPool::sIndexBytesPooled = 0; +U32 LLVertexBuffer::sAllocatedIndexBytes = 0; +U32 LLVertexBuffer::sIndexCount = 0; -LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ; +LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL; U32 LLVertexBuffer::sBindCount = 0; U32 LLVertexBuffer::sSetCount = 0; S32 LLVertexBuffer::sCount = 0; S32 LLVertexBuffer::sGLCount = 0; S32 LLVertexBuffer::sMappedCount = 0; -BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ; -BOOL LLVertexBuffer::sEnableVBOs = TRUE; +bool LLVertexBuffer::sDisableVBOMapping = false; +bool LLVertexBuffer::sEnableVBOs = true; U32 LLVertexBuffer::sGLRenderBuffer = 0; U32 LLVertexBuffer::sGLRenderArray = 0; U32 LLVertexBuffer::sGLRenderIndices = 0; U32 LLVertexBuffer::sLastMask = 0; -BOOL LLVertexBuffer::sVBOActive = FALSE; -BOOL LLVertexBuffer::sIBOActive = FALSE; +bool LLVertexBuffer::sVBOActive = false; +bool LLVertexBuffer::sIBOActive = false; U32 LLVertexBuffer::sAllocatedBytes = 0; -BOOL LLVertexBuffer::sMapped = FALSE; -BOOL LLVertexBuffer::sUseStreamDraw = TRUE; -BOOL LLVertexBuffer::sUseVAO = FALSE; -BOOL LLVertexBuffer::sPreferStreamDraw = FALSE; +U32 LLVertexBuffer::sVertexCount = 0; +bool LLVertexBuffer::sMapped = false; +bool LLVertexBuffer::sUseStreamDraw = true; +bool LLVertexBuffer::sUseVAO = false; +bool LLVertexBuffer::sPreferStreamDraw = false; const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms @@ -134,39 +174,35 @@ public: }; -//which power of 2 is i? -//assumes i is a power of 2 > 0 -U32 wpo2(U32 i) -{ - llassert(i > 0); - llassert(nhpo2(i) == i); - - U32 r = 0; - - while (i >>= 1) ++r; - - return r; -} - volatile U8* LLVBOPool::allocate(U32& name, U32 size) { - llassert(nhpo2(size) == size); + llassert(vbo_block_size(size) == size); + + volatile U8* ret = NULL; - U32 i = wpo2(size); +#if LL_VBO_POOLING + + U32 i = vbo_block_index(size); if (mFreeList.size() <= i) { mFreeList.resize(i+1); } - volatile U8* ret = NULL; - if (mFreeList[i].empty()) { //make a new buffer glGenBuffersARB(1, &name); glBindBufferARB(mType, name); - LLVertexBuffer::sAllocatedBytes += size; + + if (mType == GL_ARRAY_BUFFER_ARB) + { + LLVertexBuffer::sAllocatedBytes += size; + } + else + { + LLVertexBuffer::sAllocatedIndexBytes += size; + } if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) { @@ -185,36 +221,91 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size) name = mFreeList[i].front().mGLName; ret = mFreeList[i].front().mClientData; - sBytesPooled -= size; + if (mType == GL_ARRAY_BUFFER_ARB) + { + sBytesPooled -= size; + } + else + { + sIndexBytesPooled -= 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; } void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) { - llassert(nhpo2(size) == size); + llassert(vbo_block_size(size) == size); + +#if LL_VBO_POOLING - U32 i = wpo2(size); + U32 i = vbo_block_index(size); llassert(mFreeList.size() > i); Record rec; rec.mGLName = name; rec.mClientData = buffer; - - sBytesPooled += size; - if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB) + if (buffer == NULL) { glDeleteBuffersARB(1, &rec.mGLName); } else { + if (mType == GL_ARRAY_BUFFER_ARB) + { + sBytesPooled += size; + } + else + { + sIndexBytesPooled += size; + } mFreeList[i].push_back(rec); } +#else //no pooling + glDeleteBuffersARB(1, &name); + ll_aligned_free_16((U8*) buffer); + + if (mType == GL_ARRAY_BUFFER_ARB) + { + LLVertexBuffer::sAllocatedBytes -= size; + } + else + { + LLVertexBuffer::sAllocatedIndexBytes -= size; + } +#endif } void LLVBOPool::cleanup() @@ -238,8 +329,16 @@ void LLVBOPool::cleanup() l.pop_front(); - LLVertexBuffer::sAllocatedBytes -= size; - sBytesPooled -= size; + if (mType == GL_ARRAY_BUFFER_ARB) + { + sBytesPooled -= size; + LLVertexBuffer::sAllocatedBytes -= size; + } + else + { + sIndexBytesPooled -= size; + LLVertexBuffer::sAllocatedIndexBytes -= size; + } } size *= 2; @@ -283,7 +382,13 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { if (sLastMask != data_mask) { - BOOL error = FALSE; + bool error = false; + + if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 30) + { + //make sure texture index is disabled + data_mask = data_mask & ~MAP_TEXTURE_INDEX; + } if (LLGLSLShader::sNoFixedFunction) { @@ -344,7 +449,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { if (gDebugSession) { - error = TRUE; + error = true; gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl; } else @@ -364,7 +469,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) if (gDebugSession) { - error = TRUE; + error = true; gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl; } else @@ -430,7 +535,7 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con U32 count = pos.size(); llassert_always(norm.size() >= pos.size()); - llassert_always(count > 0) ; + llassert_always(count > 0); unbind(); @@ -548,7 +653,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { validateRange(start, end, count, indices_offset); - mMappable = FALSE; + mMappable = false; gGL.syncMatrices(); llassert(mNumVerts >= 0); @@ -603,7 +708,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - mMappable = FALSE; + mMappable = false; gGL.syncMatrices(); llassert(mNumIndices >= 0); @@ -649,7 +754,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - mMappable = FALSE; + mMappable = false; gGL.syncMatrices(); llassert(mNumVerts >= 0); @@ -689,23 +794,13 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const //static void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) { - sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ; - sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ; + sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject; + sDisableVBOMapping = sEnableVBOs && no_vbo_mapping; - if(!sPrivatePoolp) + if (!sPrivatePoolp) { - sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ; + sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC); } - - sStreamVBOPool.mType = GL_ARRAY_BUFFER_ARB; - sStreamVBOPool.mUsage= GL_STREAM_DRAW_ARB; - sStreamIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB; - sStreamIBOPool.mUsage= GL_STREAM_DRAW_ARB; - - sDynamicVBOPool.mType = GL_ARRAY_BUFFER_ARB; - sDynamicVBOPool.mUsage= GL_DYNAMIC_DRAW_ARB; - sDynamicIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB; - sDynamicIBOPool.mUsage= GL_DYNAMIC_DRAW_ARB; } //static @@ -718,18 +813,18 @@ void LLVertexBuffer::unbind() #endif sGLRenderArray = 0; sGLRenderIndices = 0; - sIBOActive = FALSE; + sIBOActive = false; } if (sVBOActive) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - sVBOActive = FALSE; + sVBOActive = false; } if (sIBOActive) { glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - sIBOActive = FALSE; + sIBOActive = false; } sGLRenderBuffer = 0; @@ -751,73 +846,80 @@ void LLVertexBuffer::cleanupClass() if(sPrivatePoolp) { - LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ; - sPrivatePoolp = NULL ; + LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp); + sPrivatePoolp = NULL; } } //---------------------------------------------------------------------------- -LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : - LLRefCount(), - - mNumVerts(0), - mNumIndices(0), - mUsage(usage), - mGLBuffer(0), - mGLArray(0), - mGLIndices(0), - mMappedData(NULL), - mMappedIndexData(NULL), - mVertexLocked(FALSE), - mIndexLocked(FALSE), - mFinal(FALSE), - mEmpty(TRUE), - mFence(NULL) +S32 LLVertexBuffer::determineUsage(S32 usage) { - LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR); - mFence = NULL; + S32 ret_usage = usage; + if (!sEnableVBOs) { - mUsage = 0 ; + ret_usage = 0; } - - if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw) + + if (ret_usage == GL_STREAM_DRAW_ARB && !sUseStreamDraw) { - mUsage = 0; + ret_usage = 0; } - if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw) + if (ret_usage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw) { - mUsage = GL_STREAM_DRAW_ARB; + ret_usage = GL_STREAM_DRAW_ARB; } - - if (mUsage == 0 && LLRender::sGLCoreProfile) + + if (ret_usage == 0 && LLRender::sGLCoreProfile) { //MUST use VBOs for all rendering - mUsage = GL_STREAM_DRAW_ARB; + ret_usage = GL_STREAM_DRAW_ARB; } - - if (mUsage && mUsage != GL_STREAM_DRAW_ARB) + + if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB) { //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default if (sDisableVBOMapping) { //always use stream draw if VBO mapping is disabled - mUsage = GL_STREAM_DRAW_ARB; + ret_usage = GL_STREAM_DRAW_ARB; } else { - mUsage = GL_DYNAMIC_DRAW_ARB; + ret_usage = GL_DYNAMIC_DRAW_ARB; } } + return ret_usage; +} - if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping) - { - mMappable = TRUE; - } - else - { - mMappable = FALSE; - } +LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : + LLRefCount(), + + mNumVerts(0), + mNumIndices(0), + mAlignedOffset(0), + mAlignedIndexOffset(0), + mSize(0), + mIndicesSize(0), + mTypeMask(typemask), + mUsage(LLVertexBuffer::determineUsage(usage)), + mGLBuffer(0), + mGLIndices(0), + mGLArray(0), + mMappedData(NULL), + mMappedIndexData(NULL), + mMappedDataUsingVBOs(false), + mMappedIndexDataUsingVBOs(false), + mVertexLocked(false), + mIndexLocked(false), + mFinal(false), + mEmpty(true), + mMappable(false), + mFence(NULL) +{ + LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR); + + mMappable = (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping); //zero out offsets for (U32 i = 0; i < TYPE_MAX; i++) @@ -825,12 +927,6 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mOffsets[i] = 0; } - mTypeMask = typemask; - mSize = 0; - mIndicesSize = 0; - mAlignedOffset = 0; - mAlignedIndexOffset = 0; - sCount++; } @@ -902,7 +998,10 @@ LLVertexBuffer::~LLVertexBuffer() mFence = NULL; - llassert_always(!mMappedData && !mMappedIndexData) ; + sVertexCount -= mNumVerts; + sIndexCount -= mNumIndices; + + llassert_always(!mMappedData && !mMappedIndexData); }; void LLVertexBuffer::placeFence() const @@ -933,7 +1032,7 @@ void LLVertexBuffer::waitFence() const void LLVertexBuffer::genBuffer(U32 size) { - mSize = nhpo2(size); + mSize = vbo_block_size(size); if (mUsage == GL_STREAM_DRAW_ARB) { @@ -949,7 +1048,7 @@ void LLVertexBuffer::genBuffer(U32 size) void LLVertexBuffer::genIndices(U32 size) { - mIndicesSize = nhpo2(size); + mIndicesSize = vbo_block_size(size); if (mUsage == GL_STREAM_DRAW_ARB) { @@ -1011,9 +1110,11 @@ void LLVertexBuffer::createGLBuffer(U32 size) return; } - mEmpty = TRUE; + mEmpty = true; - if (useVBOs()) + mMappedDataUsingVBOs = useVBOs(); + + if (mMappedDataUsingVBOs) { genBuffer(size); } @@ -1040,12 +1141,14 @@ void LLVertexBuffer::createGLIndices(U32 size) return; } - mEmpty = TRUE; + mEmpty = true; //pad by 16 bytes for aligned copies size += 16; - if (useVBOs()) + mMappedIndexDataUsingVBOs = useVBOs(); + + if (mMappedIndexDataUsingVBOs) { //pad by another 16 bytes for VBO pointer adjustment size += 16; @@ -1065,15 +1168,15 @@ void LLVertexBuffer::destroyGLBuffer() LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_BUFFER); if (mGLBuffer) { - if (useVBOs()) + if (mMappedDataUsingVBOs) { releaseBuffer(); } else { - FREE_MEM(sPrivatePoolp, (void*) mMappedData) ; + FREE_MEM(sPrivatePoolp, (void*) mMappedData); mMappedData = NULL; - mEmpty = TRUE; + mEmpty = true; } } @@ -1086,15 +1189,15 @@ void LLVertexBuffer::destroyGLIndices() LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_INDICES); if (mGLIndices) { - if (useVBOs()) + if (mMappedIndexDataUsingVBOs) { releaseIndices(); } else { - FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData) ; + FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData); mMappedIndexData = NULL; - mEmpty = TRUE; + mEmpty = true; } } @@ -1121,7 +1224,9 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) createGLBuffer(needed_size); } + sVertexCount -= mNumVerts; mNumVerts = nverts; + sVertexCount += mNumVerts; } void LLVertexBuffer::updateNumIndices(S32 nindices) @@ -1137,7 +1242,9 @@ void LLVertexBuffer::updateNumIndices(S32 nindices) createGLIndices(needed_size); } + sIndexCount -= mNumIndices; mNumIndices = nindices; + sIndexCount += mNumIndices; } void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) @@ -1199,7 +1306,7 @@ void LLVertexBuffer::setupVertexArray() 1, //TYPE_WEIGHT, 4, //TYPE_WEIGHT4, 4, //TYPE_CLOTHWEIGHT, - 1, //TYPE_TEXTURE_INDEX + 4, //TYPE_TEXTURE_INDEX }; U32 attrib_type[] = @@ -1216,7 +1323,24 @@ void LLVertexBuffer::setupVertexArray() GL_FLOAT, //TYPE_WEIGHT, GL_FLOAT, //TYPE_WEIGHT4, GL_FLOAT, //TYPE_CLOTHWEIGHT, - GL_FLOAT, //TYPE_TEXTURE_INDEX + GL_UNSIGNED_BYTE, //TYPE_TEXTURE_INDEX + }; + + bool attrib_integer[] = + { + false, //TYPE_VERTEX, + false, //TYPE_NORMAL, + false, //TYPE_TEXCOORD0, + false, //TYPE_TEXCOORD1, + false, //TYPE_TEXCOORD2, + false, //TYPE_TEXCOORD3, + false, //TYPE_COLOR, + false, //TYPE_EMISSIVE, + false, //TYPE_BINORMAL, + false, //TYPE_WEIGHT, + false, //TYPE_WEIGHT4, + false, //TYPE_CLOTHWEIGHT, + true, //TYPE_TEXTURE_INDEX }; U32 attrib_normalized[] = @@ -1244,7 +1368,21 @@ void LLVertexBuffer::setupVertexArray() if (mTypeMask & (1 << i)) { glEnableVertexAttribArrayARB(i); - glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]); + + if (attrib_integer[i]) + { +#if !LL_DARWIN + //glVertexattribIPointer requires GLSL 1.30 or later + if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) + { + glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], (void*) mOffsets[i]); + } +#endif + } + else + { + glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]); + } } else { @@ -1279,16 +1417,10 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) } } -BOOL LLVertexBuffer::useVBOs() const +bool LLVertexBuffer::useVBOs() const { //it's generally ineffective to use VBO for things that are streaming on apple - - if (!mUsage) - { - return FALSE; - } - - return TRUE; + return (mUsage != 0); } //---------------------------------------------------------------------------- @@ -1368,7 +1500,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo if (!mVertexLocked) { LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES); - mVertexLocked = TRUE; + mVertexLocked = true; sMappedCount++; stop_glerror(); @@ -1447,17 +1579,17 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo { log_glerror(); - //check the availability of memory - LLMemory::logMemoryInfo(TRUE) ; + //check the availability of memory + LLMemory::logMemoryInfo(true); if(mMappable) { //-------------------- //print out more debug info before crash - llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; - GLint size ; - glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ; - llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ; + llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl; + GLint size; + glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size); + llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl; //-------------------- GLint buff; @@ -1472,7 +1604,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } else { - llerrs << "memory allocation for vertex data failed." << llendl ; + llerrs << "memory allocation for vertex data failed." << llendl; } } } @@ -1547,7 +1679,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range { LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES); - mIndexLocked = TRUE; + mIndexLocked = true; sMappedCount++; stop_glerror(); @@ -1626,7 +1758,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range if (!mMappedIndexData) { log_glerror(); - LLMemory::logMemoryInfo(TRUE) ; + LLMemory::logMemoryInfo(true); if(mMappable) { @@ -1641,7 +1773,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range } else { - llerrs << "memory allocation for Index data failed. " << llendl ; + llerrs << "memory allocation for Index data failed. " << llendl; } } } @@ -1672,10 +1804,10 @@ void LLVertexBuffer::unmapBuffer() LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER); if (!useVBOs()) { - return ; //nothing to unmap + return; //nothing to unmap } - bool updated_all = false ; + bool updated_all = false; if (mMappedData && mVertexLocked) { @@ -1742,7 +1874,7 @@ void LLVertexBuffer::unmapBuffer() mMappedData = NULL; } - mVertexLocked = FALSE ; + mVertexLocked = false; sMappedCount--; } @@ -1806,16 +1938,16 @@ void LLVertexBuffer::unmapBuffer() glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); stop_glerror(); - mMappedIndexData = NULL ; + mMappedIndexData = NULL; } - mIndexLocked = FALSE ; + mIndexLocked = false; sMappedCount--; } if(updated_all) { - mEmpty = FALSE; + mEmpty = false; } } @@ -1835,12 +1967,12 @@ template <class T,S32 type> struct VertexBufferStrider if (ptr == NULL) { llwarns << "mapIndexBuffer failed!" << llendl; - return FALSE; + return false; } strider = (T*)ptr; strider.setStride(0); - return TRUE; + return true; } else if (vbo.hasDataType(type)) { @@ -1851,18 +1983,18 @@ template <class T,S32 type> struct VertexBufferStrider if (ptr == NULL) { llwarns << "mapVertexBuffer failed!" << llendl; - return FALSE; + return false; } strider = (T*)ptr; strider.setStride(stride); - return TRUE; + return true; } else { llerrs << "VertexBufferStrider could not find valid vertex data." << llendl; } - return FALSE; + return false; } }; @@ -1961,7 +2093,7 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind) glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); sGLRenderBuffer = mGLBuffer; sBindCount++; - sVBOActive = TRUE; + sVBOActive = true; if (mGLArray) { @@ -1993,7 +2125,7 @@ bool LLVertexBuffer::bindGLIndices(bool force_bind) sGLRenderIndices = mGLIndices; stop_glerror(); sBindCount++; - sIBOActive = TRUE; + sIBOActive = true; ret = true; } @@ -2015,7 +2147,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER); //set up pointers if the data mask is different ... - BOOL setup = (sLastMask != data_mask); + bool setup = (sLastMask != data_mask); if (gDebugGL && data_mask != 0) { //make sure data requirements are fulfilled @@ -2049,21 +2181,17 @@ void LLVertexBuffer::setBuffer(U32 data_mask) if (mGLArray) { bindGLArray(); - setup = FALSE; //do NOT perform pointer setup if using VAO + setup = false; //do NOT perform pointer setup if using VAO } else { - if (bindGLBuffer()) - { - setup = TRUE; - } - if (bindGLIndices()) - { - setup = TRUE; - } + const bool bindBuffer = bindGLBuffer(); + const bool bindIndices = bindGLIndices(); + + setup = setup || bindBuffer || bindIndices; } - BOOL error = FALSE; + bool error = false; if (gDebugGL && !mGLArray) { GLint buff; @@ -2072,7 +2200,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { if (gDebugSession) { - error = TRUE; + error = true; gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl; } else @@ -2088,7 +2216,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { if (gDebugSession) { - error = TRUE; + error = true; gFailLog << "Invalid GL index buffer bound: " << buff << std::endl; } else @@ -2110,7 +2238,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) #endif sGLRenderArray = 0; sGLRenderIndices = 0; - sIBOActive = FALSE; + sIBOActive = false; } if (mGLBuffer) @@ -2119,13 +2247,13 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); sBindCount++; - sVBOActive = FALSE; - setup = TRUE; // ... or a VBO is deactivated + sVBOActive = false; + setup = true; // ... or a VBO is deactivated } if (sGLRenderBuffer != mGLBuffer) { sGLRenderBuffer = mGLBuffer; - setup = TRUE; // ... or a client memory pointer changed + setup = true; // ... or a client memory pointer changed } } if (mGLIndices) @@ -2134,7 +2262,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); sBindCount++; - sIBOActive = FALSE; + sIBOActive = false; } sGLRenderIndices = mGLIndices; @@ -2222,25 +2350,28 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) { S32 loc = TYPE_WEIGHT; void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); - glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); + glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); } if (data_mask & MAP_WEIGHT4) { S32 loc = TYPE_WEIGHT4; void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]); - glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); } if (data_mask & MAP_CLOTHWEIGHT) { S32 loc = TYPE_CLOTHWEIGHT; void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); - glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); } - if (data_mask & MAP_TEXTURE_INDEX) + if (data_mask & MAP_TEXTURE_INDEX && + (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later { +#if !LL_DARWIN S32 loc = TYPE_TEXTURE_INDEX; void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12); - glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + glVertexAttribIPointer(loc, 4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); +#endif } if (data_mask & MAP_VERTEX) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index e1cbfd3b61..7477dec3ad 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -55,9 +55,15 @@ class LLVBOPool { public: static U32 sBytesPooled; + static U32 sIndexBytesPooled; + + LLVBOPool(U32 vboUsage, U32 vboType) + : mUsage(vboUsage) + , mType(vboType) + {} - U32 mUsage; - U32 mType; + const U32 mUsage; + const U32 mType; //size MUST be a power of 2 volatile U8* allocate(U32& name, U32 size); @@ -88,7 +94,7 @@ public: //============================================================================ // base class -class LLPrivateMemoryPool ; +class LLPrivateMemoryPool; class LLVertexBuffer : public LLRefCount { public: @@ -103,6 +109,7 @@ public: }; LLVertexBuffer(const LLVertexBuffer& rhs) + : mUsage(rhs.mUsage) { *this = rhs; } @@ -118,9 +125,9 @@ public: static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; - static BOOL sUseStreamDraw; - static BOOL sUseVAO; - static BOOL sPreferStreamDraw; + static bool sUseStreamDraw; + static bool sUseVAO; + static bool sPreferStreamDraw; static void initClass(bool use_vbo, bool no_vbo_mapping); static void cleanupClass(); @@ -201,7 +208,7 @@ protected: void destroyGLIndices(); void updateNumVerts(S32 nverts); void updateNumIndices(S32 nindices); - virtual BOOL useVBOs() const; + bool useVBOs() const; void unmapBuffer(); public: @@ -239,8 +246,8 @@ public: bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); - BOOL isEmpty() const { return mEmpty; } - BOOL isLocked() const { return mVertexLocked || mIndexLocked; } + bool isEmpty() const { return mEmpty; } + bool isLocked() const { return mVertexLocked || mIndexLocked; } S32 getNumVerts() const { return mNumVerts; } S32 getNumIndices() const { return mNumIndices; } @@ -254,7 +261,7 @@ public: volatile U8* getMappedIndices() const { return mMappedIndexData; } S32 getOffset(S32 type) const { return mOffsets[type]; } S32 getUsage() const { return mUsage; } - BOOL isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; } + bool isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? true : false; } void draw(U32 mode, U32 count, U32 indices_offset) const; void drawArrays(U32 mode, U32 offset, U32 count) const; @@ -274,18 +281,25 @@ protected: S32 mSize; S32 mIndicesSize; U32 mTypeMask; - S32 mUsage; // GL usage + + const S32 mUsage; // GL usage + U32 mGLBuffer; // GL VBO handle U32 mGLIndices; // GL IBO handle U32 mGLArray; // GL VAO handle volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) - BOOL mVertexLocked; // if TRUE, vertex buffer is being or has been written to in client memory - BOOL mIndexLocked; // if TRUE, index buffer is being or has been written to in client memory - BOOL mFinal; // if TRUE, buffer can not be mapped again - BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded. - mutable BOOL mMappable; // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData) + + U32 mMappedDataUsingVBOs : 1; + U32 mMappedIndexDataUsingVBOs : 1; + U32 mVertexLocked : 1; // if true, vertex buffer is being or has been written to in client memory + U32 mIndexLocked : 1; // if true, index buffer is being or has been written to in client memory + U32 mFinal : 1; // if true, buffer can not be mapped again + U32 mEmpty : 1; // if true, client buffer is empty (or NULL). Old values have been discarded. + + mutable bool mMappable; // if true, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData) + S32 mOffsets[TYPE_MAX]; std::vector<MappedRegion> mMappedVertexRegions; @@ -296,28 +310,32 @@ protected: void placeFence() const; void waitFence() const; + static S32 determineUsage(S32 usage); private: - static LLPrivateMemoryPool* sPrivatePoolp ; + static LLPrivateMemoryPool* sPrivatePoolp; public: static S32 sCount; static S32 sGLCount; static S32 sMappedCount; - static BOOL sMapped; + static bool sMapped; typedef std::list<LLVertexBuffer*> buffer_list_t; - static BOOL sDisableVBOMapping; //disable glMapBufferARB - static BOOL sEnableVBOs; + static bool sDisableVBOMapping; //disable glMapBufferARB + static bool sEnableVBOs; static S32 sTypeSize[TYPE_MAX]; static U32 sGLMode[LLRender::NUM_MODES]; static U32 sGLRenderBuffer; static U32 sGLRenderArray; static U32 sGLRenderIndices; - static BOOL sVBOActive; - static BOOL sIBOActive; + static bool sVBOActive; + static bool sIBOActive; static U32 sLastMask; static U32 sAllocatedBytes; + static U32 sAllocatedIndexBytes; + static U32 sVertexCount; + static U32 sIndexCount; static U32 sBindCount; static U32 sSetCount; }; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 772f173f17..20c3456a56 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -12,7 +12,6 @@ include(LLRender) include(LLWindow) include(LLVFS) include(LLXML) -include(LLXUIXML) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -24,7 +23,6 @@ include_directories( ${LLWINDOW_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLXUIXML_INCLUDE_DIRS} ) set(llui_SOURCE_FILES @@ -83,7 +81,6 @@ set(llui_SOURCE_FILES llscrolllistcolumn.cpp llscrolllistctrl.cpp llscrolllistitem.cpp - llsdparam.cpp llsearcheditor.cpp llslider.cpp llsliderctrl.cpp @@ -100,11 +97,13 @@ set(llui_SOURCE_FILES lltextutil.cpp lltextvalidate.cpp lltimectrl.cpp + lltrans.cpp lltransutil.cpp lltoggleablemenu.cpp lltoolbar.cpp lltooltip.cpp llui.cpp + lluicolor.cpp lluicolortable.cpp lluictrl.cpp lluictrlfactory.cpp @@ -121,6 +120,7 @@ set(llui_SOURCE_FILES llview.cpp llviewquery.cpp llwindowshade.cpp + llxuiparser.cpp ) set(llui_HEADER_FILES @@ -189,7 +189,6 @@ set(llui_HEADER_FILES llscrolllistcolumn.h llscrolllistctrl.h llscrolllistitem.h - llsdparam.h llsliderctrl.h llslider.h llspinctrl.h @@ -208,6 +207,7 @@ set(llui_HEADER_FILES lltoggleablemenu.h lltoolbar.h lltooltip.h + lltrans.h lltransutil.h lluicolortable.h lluiconstants.h @@ -215,6 +215,7 @@ set(llui_HEADER_FILES lluictrl.h lluifwd.h llui.h + lluicolor.h lluiimage.h lluistring.h llundo.h @@ -228,6 +229,7 @@ set(llui_HEADER_FILES llview.h llviewquery.h llwindowshade.h + llxuiparser.h ) set_source_files_properties(${llui_HEADER_FILES} diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 7a5f9f9fd6..c025cd7939 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -976,7 +976,7 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child) gGL.matrixMode(LLRender::MM_MODELVIEW); LLUI::pushMatrix(); { - LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom, 0.f); + LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom); child->draw(); } diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index f0d92d597a..705fe16559 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -908,9 +908,9 @@ void LLButton::draw() // Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars. mLastDrawCharsCount = mGLFont->render(label, 0, (F32)x, - (F32)(mBottomVPad + y_offset), + (F32)(getRect().getHeight() / 2 + mBottomVPad), label_color % alpha, - mHAlign, LLFontGL::BOTTOM, + mHAlign, LLFontGL::VCENTER, LLFontGL::NORMAL, mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, S32_MAX, text_width, diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp index 6910b962a1..14173fdbb0 100644 --- a/indra/llui/llclipboard.cpp +++ b/indra/llui/llclipboard.cpp @@ -34,109 +34,113 @@ #include "llview.h" #include "llwindow.h" -// Global singleton -LLClipboard gClipboard; - - -LLClipboard::LLClipboard() +LLClipboard::LLClipboard() : + mGeneration(0) { - mSourceItem = NULL; + reset(); } - LLClipboard::~LLClipboard() { + reset(); } - -void LLClipboard::copyFromSubstring(const LLWString &src, S32 pos, S32 len, const LLUUID& source_id ) +void LLClipboard::reset() { - mSourceID = source_id; - mString = src.substr(pos, len); - LLView::getWindow()->copyTextToClipboard( mString ); + // Increment the clipboard count + mGeneration++; + // Clear the clipboard + mObjects.clear(); + mCutMode = false; + mString = LLWString(); } -void LLClipboard::copyFromString(const LLWString &src, const LLUUID& source_id ) +// Copy the input uuid to the LL clipboard +bool LLClipboard::copyToClipboard(const LLUUID& src, const LLAssetType::EType type) { - mSourceID = source_id; - mString = src; - LLView::getWindow()->copyTextToClipboard( mString ); + reset(); + return addToClipboard(src, type); } -const LLWString& LLClipboard::getPasteWString( LLUUID* source_id ) +// Add the input uuid to the LL clipboard +// Convert the uuid to string and concatenate that string to the system clipboard if legit +bool LLClipboard::addToClipboard(const LLUUID& src, const LLAssetType::EType type) { - if( mSourceID.notNull() ) + bool res = false; + if (src.notNull()) { - LLWString temp_string; - LLView::getWindow()->pasteTextFromClipboard(temp_string); - - if( temp_string != mString ) + res = true; + if (LLAssetType::lookupIsAssetIDKnowable(type)) { - mSourceID.setNull(); - mString = temp_string; + LLWString source = utf8str_to_wstring(src.asString()); + res = addToClipboard(source, 0, source.size()); + } + if (res) + { + mObjects.push_back(src); + mGeneration++; } } - else - { - LLView::getWindow()->pasteTextFromClipboard(mString); - } + return res; +} - if( source_id ) +bool LLClipboard::pasteFromClipboard(std::vector<LLUUID>& inv_objects) const +{ + bool res = false; + S32 count = mObjects.size(); + if (count > 0) { - *source_id = mSourceID; + res = true; + inv_objects.clear(); + for (S32 i = 0; i < count; i++) + { + inv_objects.push_back(mObjects[i]); + } } - - return mString; + return res; } +// Returns true if the LL Clipboard has pasteable items in it +bool LLClipboard::hasContents() const +{ + return (mObjects.size() > 0); +} -BOOL LLClipboard::canPasteString() const +// Returns true if the input uuid is in the list of clipboard objects +bool LLClipboard::isOnClipboard(const LLUUID& object) const { - return LLView::getWindow()->isClipboardTextAvailable(); + std::vector<LLUUID>::const_iterator iter = std::find(mObjects.begin(), mObjects.end(), object); + return (iter != mObjects.end()); } +// Copy the input string to the LL and the system clipboard +bool LLClipboard::copyToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary) +{ + return addToClipboard(src, pos, len, use_primary); +} -void LLClipboard::copyFromPrimarySubstring(const LLWString &src, S32 pos, S32 len, const LLUUID& source_id ) +// Concatenate the input string to the LL and the system clipboard +bool LLClipboard::addToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary) { - mSourceID = source_id; mString = src.substr(pos, len); - LLView::getWindow()->copyTextToPrimary( mString ); + return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString)); } - -const LLWString& LLClipboard::getPastePrimaryWString( LLUUID* source_id ) +// Copy the System clipboard to the output string. +// Manage the LL Clipboard / System clipboard consistency +bool LLClipboard::pasteFromClipboard(LLWString &dst, bool use_primary) { - if( mSourceID.notNull() ) - { - LLWString temp_string; - LLView::getWindow()->pasteTextFromPrimary(temp_string); - - if( temp_string != mString ) - { - mSourceID.setNull(); - mString = temp_string; - } - } - else - { - LLView::getWindow()->pasteTextFromPrimary(mString); - } - - if( source_id ) + bool res = (use_primary ? LLView::getWindow()->pasteTextFromPrimary(dst) : LLView::getWindow()->pasteTextFromClipboard(dst)); + if (res) { - *source_id = mSourceID; + mString = dst; } - - return mString; + return res; } - -BOOL LLClipboard::canPastePrimaryString() const +// Return true if there's something on the System clipboard +bool LLClipboard::isTextAvailable(bool use_primary) const { - return LLView::getWindow()->isPrimaryTextAvailable(); + return (use_primary ? LLView::getWindow()->isPrimaryTextAvailable() : LLView::getWindow()->isClipboardTextAvailable()); } -void LLClipboard::setSourceObject(const LLUUID& source_id, LLAssetType::EType type) -{ - mSourceItem = new LLInventoryObject (source_id, LLUUID::null, type, ""); -} diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h index 9371b94284..fd2e7610df 100644 --- a/indra/llui/llclipboard.h +++ b/indra/llui/llclipboard.h @@ -27,46 +27,68 @@ #ifndef LL_LLCLIPBOARD_H #define LL_LLCLIPBOARD_H +#include <boost/function.hpp> #include "llstring.h" #include "lluuid.h" #include "stdenums.h" +#include "llsingleton.h" +#include "llassettype.h" #include "llinventory.h" +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLClipboard +// +// This class is used to cut/copy/paste text strings and inventory items around +// the world. Use LLClipboard::instance().method() to use its methods. +// Note that the text and UUIDs are loosely coupled only. There are few cases +// where the viewer does offer a serialized version of the UUID on the clipboard. +// In those case, the text is overridden when copying/cutting the item. +// In all other cases, the text and the UUIDs are very much independent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLClipboard +class LLClipboard : public LLSingleton<LLClipboard> { public: LLClipboard(); ~LLClipboard(); + + // Clears the clipboard + void reset(); + // Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state) + int getGeneration() const { return mGeneration; } - /* We support two flavors of clipboard. The default is the explicitly - copy-and-pasted clipboard. The second is the so-called 'primary' clipboard - which is implicitly copied upon selection on platforms which expect this - (i.e. X11/Linux). */ - - void copyFromSubstring(const LLWString ©_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null ); - void copyFromString(const LLWString ©_from, const LLUUID& source_id = LLUUID::null ); - BOOL canPasteString() const; - const LLWString& getPasteWString(LLUUID* source_id = NULL); + // Text strings management: + // ------------------------ + // We support two flavors of text clipboards. The default is the explicitly + // copy-and-pasted clipboard. The second is the so-called 'primary' clipboard + // which is implicitly copied upon selection on platforms which expect this + // (i.e. X11/Linux, Mac). + bool copyToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false); + bool addToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false); + bool pasteFromClipboard(LLWString& dst, bool use_primary = false); + bool isTextAvailable(bool use_primary = false) const; + + // Object list management: + // ----------------------- + // Clears and adds one single object to the clipboard + bool copyToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE); + // Adds one object to the current list of objects on the clipboard + bool addToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE); + // Gets a copy of the objects on the clipboard + bool pasteFromClipboard(std::vector<LLUUID>& inventory_objects) const; + + bool hasContents() const; // True if the clipboard has pasteable objects + bool isOnClipboard(const LLUUID& object) const; // True if the input object uuid is on the clipboard - void copyFromPrimarySubstring(const LLWString ©_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null ); - BOOL canPastePrimaryString() const; - const LLWString& getPastePrimaryWString(LLUUID* source_id = NULL); + bool isCutMode() const { return mCutMode; } + void setCutMode(bool mode) { mCutMode = mode; mGeneration++; } - // Support clipboard for object known only by their uuid and asset type - void setSourceObject(const LLUUID& source_id, LLAssetType::EType type); - const LLInventoryObject* getSourceObject() { return mSourceItem; } - private: - LLUUID mSourceID; - LLWString mString; - LLInventoryObject* mSourceItem; + std::vector<LLUUID> mObjects; // Objects on the clipboard. Can be empty while mString contains something licit (e.g. text from chat) + LLWString mString; // The text string. If mObjects is not empty, this string is reflecting them (UUIDs for the moment) if the asset type is knowable. + bool mCutMode; // This is a convenience flag for the viewer. + int mGeneration; // Incremented when the clipboard changes so that interested parties can check for changes on the clipboard. }; - -// Global singleton -extern LLClipboard gClipboard; - - #endif // LL_LLCLIPBOARD_H diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 89d8842393..806d2ef3f6 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -613,7 +613,7 @@ void LLComboBox::showList() } mList->setOrigin(rect.mLeft, rect.mBottom); mList->reshape(rect.getWidth(), rect.getHeight()); - mList->translateIntoRect(root_view_local, FALSE); + mList->translateIntoRect(root_view_local); // Make sure we didn't go off bottom of screen S32 x, y; diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp index e01e331acf..e08ccb0b78 100644 --- a/indra/llui/llcontainerview.cpp +++ b/indra/llui/llcontainerview.cpp @@ -196,24 +196,24 @@ void LLContainerView::arrange(S32 width, S32 height, BOOL called_from_parent) if (total_height < height) total_height = height; + LLRect my_rect = getRect(); if (followsTop()) { - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast<LLRect&>(getRect()).mBottom = getRect().mTop - total_height; + my_rect.mBottom = my_rect.mTop - total_height; } else { - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast<LLRect&>(getRect()).mTop = getRect().mBottom + total_height; + my_rect.mTop = my_rect.mBottom + total_height; } - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast<LLRect&>(getRect()).mRight = getRect().mLeft + width; + + my_rect.mRight = my_rect.mLeft + width; + setRect(my_rect); top = total_height; if (mShowLabel) - { - top -= 20; - } + { + top -= 20; + } bottom = top; diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 42e6c3c786..5f69c6af31 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -244,7 +244,7 @@ void LLDragHandleTop::reshapeTitleBox() const LLFontGL* font = LLFontGL::getFontSansSerif(); S32 title_width = getRect().getWidth(); title_width -= LEFT_PAD + 2 * BORDER_PAD + getButtonsRect().getWidth(); - S32 title_height = llround(font->getLineHeight()); + S32 title_height = font->getLineHeight(); LLRect title_rect; title_rect.setLeftTopAndSize( LEFT_PAD, diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 33548151fd..8ca1e685a9 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -68,10 +68,10 @@ namespace LLInitParam { void TypeValues<LLFloaterEnums::EOpenPositioning>::declareValues() { - declare("none", LLFloaterEnums::OPEN_POSITIONING_NONE); - declare("cascading", LLFloaterEnums::OPEN_POSITIONING_CASCADING); - declare("centered", LLFloaterEnums::OPEN_POSITIONING_CENTERED); - declare("specified", LLFloaterEnums::OPEN_POSITIONING_SPECIFIED); + declare("relative", LLFloaterEnums::POSITIONING_RELATIVE); + declare("cascading", LLFloaterEnums::POSITIONING_CASCADING); + declare("centered", LLFloaterEnums::POSITIONING_CENTERED); + declare("specified", LLFloaterEnums::POSITIONING_SPECIFIED); } } @@ -177,9 +177,7 @@ LLFloater::Params::Params() save_visibility("save_visibility", false), can_dock("can_dock", false), show_title("show_title", true), - open_positioning("open_positioning", LLFloaterEnums::OPEN_POSITIONING_NONE), - specified_left("specified_left"), - specified_bottom("specified_bottom"), + positioning("positioning", LLFloaterEnums::POSITIONING_RELATIVE), header_height("header_height", 0), legacy_header_height("legacy_header_height", 0), close_image("close_image"), @@ -249,9 +247,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mCanClose(p.can_close), mDragOnLeft(p.can_drag_on_left), mResizable(p.can_resize), - mOpenPositioning(p.open_positioning), - mSpecifiedLeft(p.specified_left), - mSpecifiedBottom(p.specified_bottom), + mPositioning(p.positioning), mMinWidth(p.min_width), mMinHeight(p.min_height), mHeaderHeight(p.header_height), @@ -270,6 +266,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mMinimizeSignal(NULL) // mNotificationContext(NULL) { + mPosition.setFloater(*this); // mNotificationContext = new LLFloaterNotificationContext(getHandle()); // Clicks stop here. @@ -546,10 +543,18 @@ LLFloater::~LLFloater() void LLFloater::storeRectControl() { - if( mRectControl.size() > 1 ) + if (!mRectControl.empty()) { getControlGroup()->setRect( mRectControl, getRect() ); } + if (!mPosXControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE) + { + getControlGroup()->setF32( mPosXControl, mPosition.mX ); + } + if (!mPosYControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE) + { + getControlGroup()->setF32( mPosYControl, mPosition.mY ); + } } void LLFloater::storeVisibilityControl() @@ -568,23 +573,6 @@ void LLFloater::storeDockStateControl() } } -LLRect LLFloater::getSavedRect() const -{ - LLRect rect; - - if (mRectControl.size() > 1) - { - rect = getControlGroup()->getRect(mRectControl); - } - - return rect; -} - -bool LLFloater::hasSavedRect() const -{ - return !getSavedRect().isEmpty(); -} - // static std::string LLFloater::getControlName(const std::string& name, const LLSD& key) { @@ -862,7 +850,7 @@ void LLFloater::applyControlsAndPosition(LLFloater* other) { if (!applyRectControl()) { - applyPositioning(other); + applyPositioning(other, true); } } } @@ -871,29 +859,68 @@ bool LLFloater::applyRectControl() { bool saved_rect = false; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); + LLFloater* last_in_group = LLFloaterReg::getLastFloaterInGroup(mInstanceName); if (last_in_group && last_in_group != this) { // other floaters in our group, position ourselves relative to them and don't save the rect mRectControl.clear(); - mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_CASCADE_GROUP; + mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; } - else if (mRectControl.size() > 1) + else { - // If we have a saved rect, use it - const LLRect& rect = getControlGroup()->getRect(mRectControl); - saved_rect = rect.notEmpty(); - if (saved_rect) + bool rect_specified = false; + if (!mRectControl.empty()) { - setOrigin(rect.mLeft, rect.mBottom); - - if (mResizable) + // If we have a saved rect, use it + const LLRect& rect = getControlGroup()->getRect(mRectControl); + if (rect.notEmpty()) saved_rect = true; + if (saved_rect) { - reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + setOrigin(rect.mLeft, rect.mBottom); + + if (mResizable) + { + reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + } + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); + rect_specified = true; } } + + LLControlVariablePtr x_control = getControlGroup()->getControl(mPosXControl); + LLControlVariablePtr y_control = getControlGroup()->getControl(mPosYControl); + if (x_control.notNull() + && y_control.notNull() + && !x_control->isDefault() + && !y_control->isDefault()) + { + mPosition.mX = x_control->getValue().asReal(); + mPosition.mY = y_control->getValue().asReal(); + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + applyRelativePosition(); + + saved_rect = true; + } + + // remember updated position + if (rect_specified) + { + storeRectControl(); + } + } + + if (saved_rect) + { + // propagate any derived positioning data back to settings file + storeRectControl(); } + return saved_rect; } @@ -910,50 +937,56 @@ bool LLFloater::applyDockState() return docked; } -void LLFloater::applyPositioning(LLFloater* other) +void LLFloater::applyPositioning(LLFloater* other, bool on_open) { // Otherwise position according to the positioning code - switch (mOpenPositioning) + switch (mPositioning) { - case LLFloaterEnums::OPEN_POSITIONING_CENTERED: + case LLFloaterEnums::POSITIONING_CENTERED: center(); break; - case LLFloaterEnums::OPEN_POSITIONING_SPECIFIED: - { - // Translate relative to snap rect - setOrigin(mSpecifiedLeft, mSpecifiedBottom); - const LLRect& snap_rect = gFloaterView->getSnapRect(); - translate(snap_rect.mLeft, snap_rect.mBottom); - translateIntoRect(snap_rect, FALSE); - } + case LLFloaterEnums::POSITIONING_SPECIFIED: break; - case LLFloaterEnums::OPEN_POSITIONING_CASCADE_GROUP: - case LLFloaterEnums::OPEN_POSITIONING_CASCADING: - if (other != NULL && other != this) + case LLFloaterEnums::POSITIONING_CASCADING: + if (!on_open) { - stackWith(*other); + applyRelativePosition(); } - else + // fall through + case LLFloaterEnums::POSITIONING_CASCADE_GROUP: + if (on_open) { - static const U32 CASCADING_FLOATER_HOFFSET = 0; - static const U32 CASCADING_FLOATER_VOFFSET = 0; + if (other != NULL && other != this) + { + stackWith(*other); + } + else + { + static const U32 CASCADING_FLOATER_HOFFSET = 0; + static const U32 CASCADING_FLOATER_VOFFSET = 0; - const LLRect& snap_rect = gFloaterView->getSnapRect(); + const LLRect& snap_rect = gFloaterView->getSnapRect(); - const S32 horizontal_offset = CASCADING_FLOATER_HOFFSET; - const S32 vertical_offset = snap_rect.getHeight() - CASCADING_FLOATER_VOFFSET; + const S32 horizontal_offset = CASCADING_FLOATER_HOFFSET; + const S32 vertical_offset = snap_rect.getHeight() - CASCADING_FLOATER_VOFFSET; - S32 rect_height = getRect().getHeight(); - setOrigin(horizontal_offset, vertical_offset - rect_height); + S32 rect_height = getRect().getHeight(); + setOrigin(horizontal_offset, vertical_offset - rect_height); - translate(snap_rect.mLeft, snap_rect.mBottom); - translateIntoRect(snap_rect, FALSE); + translate(snap_rect.mLeft, snap_rect.mBottom); + } + setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); } break; - case LLFloaterEnums::OPEN_POSITIONING_NONE: + case LLFloaterEnums::POSITIONING_RELATIVE: + { + applyRelativePosition(); + + break; + } default: // Do nothing break; @@ -1071,7 +1104,9 @@ void LLFloater::handleReshape(const LLRect& new_rect, bool by_user) if (by_user && !isMinimized()) { storeRectControl(); - mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_NONE; + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); } // if not minimized, adjust all snapped dependents to new shape @@ -1249,6 +1284,7 @@ void LLFloater::setMinimized(BOOL minimize) // Reshape *after* setting mMinimized reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); + applyPositioning(NULL, false); } make_ui_sound("UISndWindowClose"); @@ -1589,7 +1625,7 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock) if (mDocked) { setMinimized(FALSE); - mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_NONE; + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; } updateTitleButtons(); @@ -1623,7 +1659,7 @@ void LLFloater::onClickTearOff(LLFloater* self) self->openFloater(self->getKey()); // only force position for floaters that don't have that data saved - if (self->mRectControl.size() <= 1) + if (self->mRectControl.empty()) { new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight()); self->setRect(new_rect); @@ -1681,6 +1717,8 @@ LLFloater* LLFloater::getClosableFloaterFromFocus() { if (it->hasFocus()) { + LLFloater& floater = *it; + focused_floater = &floater; break; } } @@ -1800,7 +1838,7 @@ void LLFloater::draw() const LLFontGL* font = LLFontGL::getFontSansSerif(); LLRect r = getRect(); - gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, + gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - font->getLineHeight() - 1, titlebar_focus_color % alpha, 0, TRUE); } } @@ -2161,19 +2199,14 @@ LLFloaterView::LLFloaterView (const Params& p) mSnapOffsetBottom(0), mSnapOffsetRight(0) { + mSnapView = getHandle(); } // By default, adjust vertical. void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) { - S32 old_right = mLastSnapRect.mRight; - S32 old_top = mLastSnapRect.mTop; - LLView::reshape(width, height, called_from_parent); - S32 new_right = getSnapRect().mRight; - S32 new_top = getSnapRect().mTop; - mLastSnapRect = getSnapRect(); for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) @@ -2186,35 +2219,39 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) continue; } - if (!floaterp->isMinimized()) + if (!floaterp->isMinimized() && floaterp->getCanDrag()) { - LLRect r = floaterp->getRect(); + LLRect old_rect = floaterp->getRect(); + floaterp->applyPositioning(NULL, false); + LLRect new_rect = floaterp->getRect(); - // Compute absolute distance from each edge of screen - S32 left_offset = llabs(r.mLeft - 0); - S32 right_offset = llabs(old_right - r.mRight); + //LLRect r = floaterp->getRect(); - S32 top_offset = llabs(old_top - r.mTop); - S32 bottom_offset = llabs(r.mBottom - 0); + //// Compute absolute distance from each edge of screen + //S32 left_offset = llabs(r.mLeft - 0); + //S32 right_offset = llabs(old_right - r.mRight); - S32 translate_x = 0; - S32 translate_y = 0; + //S32 top_offset = llabs(old_top - r.mTop); + //S32 bottom_offset = llabs(r.mBottom - 0); - if (left_offset > right_offset) - { - translate_x = new_right - old_right; - } + S32 translate_x = new_rect.mLeft - old_rect.mLeft; + S32 translate_y = new_rect.mBottom - old_rect.mBottom; - if (top_offset < bottom_offset) - { - translate_y = new_top - old_top; - } + //if (left_offset > right_offset) + //{ + // translate_x = new_right - old_right; + //} + + //if (top_offset < bottom_offset) + //{ + // translate_y = new_top - old_top; + //} // don't reposition immovable floaters - if (floaterp->getCanDrag()) - { - floaterp->translate(translate_x, translate_y); - } + //if (floaterp->getCanDrag()) + //{ + // floaterp->translate(translate_x, translate_y); + //} BOOST_FOREACH(LLHandle<LLFloater> dependent_floater, floaterp->mDependents) { if (dependent_floater.get()) @@ -2641,6 +2678,8 @@ void LLFloaterView::refresh() } } +const S32 FLOATER_MIN_VISIBLE_PIXELS = 16; + void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside) { if (floater->getParent() != this) @@ -2694,7 +2733,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out } // move window fully onscreen - if (floater->translateIntoRect( getSnapRect(), allow_partial_outside )) + if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX )) { floater->clearSnapTarget(); } @@ -2908,9 +2947,11 @@ void LLFloater::setInstanceName(const std::string& name) std::string ctrl_name = getControlName(mInstanceName, mKey); // save_rect and save_visibility only apply to registered floaters - if (!mRectControl.empty()) + if (mSaveRect) { mRectControl = LLFloaterReg::declareRectControl(ctrl_name); + mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name); + mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name); } if (!mVisibilityControl.empty()) { @@ -2967,7 +3008,10 @@ void LLFloater::initFromParams(const LLFloater::Params& p) LLPanel::initFromParams(p); // override any follows flags - setFollows(FOLLOWS_NONE); + if (mPositioning != LLFloaterEnums::POSITIONING_SPECIFIED) + { + setFollows(FOLLOWS_NONE); + } mTitle = p.title; mShortTitle = p.short_title; @@ -2986,14 +3030,9 @@ void LLFloater::initFromParams(const LLFloater::Params& p) mSingleInstance = p.single_instance; mReuseInstance = p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance; - mOpenPositioning = p.open_positioning; - mSpecifiedLeft = p.specified_left; - mSpecifiedBottom = p.specified_bottom; + mPositioning = p.positioning; - if (p.save_rect && mRectControl.empty()) - { - mRectControl = "t"; // flag to build mRectControl name once mInstanceName is set - } + mSaveRect = p.save_rect; if (p.save_visibility) { mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set @@ -3108,7 +3147,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str params.rect.left.set(0); } params.from_xui = true; - applyXUILayout(params, parent); + applyXUILayout(params, parent, parent == gFloaterView ? gFloaterView->getSnapRect() : parent->getLocalRect()); initFromParams(params); initFloater(params); @@ -3267,5 +3306,140 @@ void LLFloater::stackWith(LLFloater& other) next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight()); setShape(next_rect); + + if (!other.getHost()) + { + other.mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; + other.setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); + } } +void LLFloater::applyRelativePosition() +{ + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + LLRect floater_screen_rect = calcScreenRect(); + + LLCoordGL new_center = mPosition.convert(); + LLCoordGL cur_center(floater_screen_rect.getCenterX(), floater_screen_rect.getCenterY()); + translate(new_center.mX - cur_center.mX, new_center.mY - cur_center.mY); +} + + +LLCoordFloater::LLCoordFloater(F32 x, F32 y, LLFloater& floater) +: coord_t((S32)x, (S32)y) +{ + mFloater = floater.getHandle(); +} + + +LLCoordFloater::LLCoordFloater(const LLCoordCommon& other, LLFloater& floater) +{ + mFloater = floater.getHandle(); + convertFromCommon(other); +} + +LLCoordFloater& LLCoordFloater::operator=(const LLCoordFloater& other) +{ + mFloater = other.mFloater; + coord_t::operator =(other); + return *this; +} + +void LLCoordFloater::setFloater(LLFloater& floater) +{ + mFloater = floater.getHandle(); +} + +bool LLCoordFloater::operator==(const LLCoordFloater& other) const +{ + return mX == other.mX && mY == other.mY && mFloater == other.mFloater; +} + +LLCoordCommon LL_COORD_FLOATER::convertToCommon() const +{ + const LLCoordFloater& self = static_cast<const LLCoordFloater&>(LLCoordFloater::getTypedCoords(*this)); + + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + + LLFloater* floaterp = mFloater.get(); + S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; + S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0; + LLCoordCommon out; + if (self.mX < -0.5f) + { + out.mX = llround(rescale(self.mX, -1.f, -0.5f, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft)); + } + else if (self.mX > 0.5f) + { + out.mX = llround(rescale(self.mX, 0.5f, 1.f, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS)); + } + else + { + out.mX = llround(rescale(self.mX, -0.5f, 0.5f, snap_rect.mLeft, snap_rect.mRight - floater_width)); + } + + if (self.mY < -0.5f) + { + out.mY = llround(rescale(self.mY, -1.f, -0.5f, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom)); + } + else if (self.mY > 0.5f) + { + out.mY = llround(rescale(self.mY, 0.5f, 1.f, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS)); + } + else + { + out.mY = llround(rescale(self.mY, -0.5f, 0.5f, snap_rect.mBottom, snap_rect.mTop - floater_height)); + } + + // return center point instead of lower left + out.mX += floater_width / 2; + out.mY += floater_height / 2; + + return out; +} + +void LL_COORD_FLOATER::convertFromCommon(const LLCoordCommon& from) +{ + LLCoordFloater& self = static_cast<LLCoordFloater&>(LLCoordFloater::getTypedCoords(*this)); + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + + + LLFloater* floaterp = mFloater.get(); + S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; + S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0; + + S32 from_x = from.mX - floater_width / 2; + S32 from_y = from.mY - floater_height / 2; + + if (from_x < snap_rect.mLeft) + { + self.mX = rescale(from_x, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft, -1.f, -0.5f); + } + else if (from_x + floater_width > snap_rect.mRight) + { + self.mX = rescale(from_x, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f); + } + else + { + self.mX = rescale(from_x, snap_rect.mLeft, snap_rect.mRight - floater_width, -0.5f, 0.5f); + } + + if (from_y < snap_rect.mBottom) + { + self.mY = rescale(from_y, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom, -1.f, -0.5f); + } + else if (from_y + floater_height > snap_rect.mTop) + { + self.mY = rescale(from_y, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f); + } + else + { + self.mY = rescale(from_y, snap_rect.mBottom, snap_rect.mTop - floater_height, -0.5f, 0.5f); + } +} diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 59b35d206f..64d6dcea04 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -64,12 +64,12 @@ namespace LLFloaterEnums { enum EOpenPositioning { - OPEN_POSITIONING_NONE, - OPEN_POSITIONING_CASCADING, - OPEN_POSITIONING_CASCADE_GROUP, - OPEN_POSITIONING_CENTERED, - OPEN_POSITIONING_SPECIFIED, - OPEN_POSITIONING_COUNT + POSITIONING_RELATIVE, + POSITIONING_CASCADING, + POSITIONING_CASCADE_GROUP, + POSITIONING_CENTERED, + POSITIONING_SPECIFIED, + POSITIONING_COUNT }; } @@ -82,6 +82,37 @@ namespace LLInitParam }; } +struct LL_COORD_FLOATER +{ + typedef F32 value_t; + + LLCoordCommon convertToCommon() const; + void convertFromCommon(const LLCoordCommon& from); +protected: + LLHandle<LLFloater> mFloater; +}; + +struct LLCoordFloater : LLCoord<LL_COORD_FLOATER> +{ + typedef LLCoord<LL_COORD_FLOATER> coord_t; + + LLCoordFloater() {} + LLCoordFloater(F32 x, F32 y, LLFloater& floater); + LLCoordFloater(const LLCoordCommon& other, LLFloater& floater); + + LLCoordFloater& operator=(const LLCoordCommon& other) + { + convertFromCommon(other); + return *this; + } + + LLCoordFloater& operator=(const LLCoordFloater& other); + + bool operator==(const LLCoordFloater& other) const; + bool operator!=(const LLCoordFloater& other) const { return !(*this == other); } + + void setFloater(LLFloater& floater); +}; class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater> { @@ -132,10 +163,7 @@ public: can_dock, show_title; - Optional<LLFloaterEnums::EOpenPositioning> open_positioning; - Optional<S32> specified_left; - Optional<S32> specified_bottom; - + Optional<LLFloaterEnums::EOpenPositioning> positioning; Optional<S32> header_height, legacy_header_height; // HACK see initFromXML() @@ -184,7 +212,7 @@ public: bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL); /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); - /*virtual*/ BOOL canSnapTo(const LLView* other_view); + /*virtual*/ BOOL canSnapTo(const LLView* other_view); /*virtual*/ void setSnappedTo(const LLView* snap_view); /*virtual*/ void setFocus( BOOL b ); /*virtual*/ void setIsChrome(BOOL is_chrome); @@ -241,8 +269,6 @@ public: BOOL isResizable() const { return mResizable; } void setResizeLimits( S32 min_width, S32 min_height ); void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } - LLRect getSavedRect() const; - bool hasSavedRect() const; static std::string getControlName(const std::string& name, const LLSD& key); static LLControlGroup* getControlGroup(); @@ -324,7 +350,7 @@ public: void enableResizeCtrls(bool enable, bool width = true, bool height = true); - bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mOpenPositioning); } + bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mPositioning); } protected: void applyControlsAndPosition(LLFloater* other); @@ -332,7 +358,9 @@ protected: virtual bool applyRectControl(); bool applyDockState(); - void applyPositioning(LLFloater* other); + void applyPositioning(LLFloater* other, bool on_open); + void applyRelativePosition(); + void storeRectControl(); void storeVisibilityControl(); void storeDockStateControl(); @@ -396,7 +424,10 @@ public: commit_signal_t* mMinimizeSignal; protected: + bool mSaveRect; std::string mRectControl; + std::string mPosXControl; + std::string mPosYControl; std::string mVisibilityControl; std::string mDocStateControl; LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg @@ -422,9 +453,8 @@ private: BOOL mDragOnLeft; BOOL mResizable; - LLFloaterEnums::EOpenPositioning mOpenPositioning; - S32 mSpecifiedLeft; - S32 mSpecifiedBottom; + LLFloaterEnums::EOpenPositioning mPositioning; + LLCoordFloater mPosition; S32 mMinWidth; S32 mMinHeight; diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index e144b68f5e..9115eb7174 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -96,7 +96,9 @@ LLFloater* LLFloaterReg::getLastFloaterCascading() { LLFloater* inst = *iter; - if (inst->getVisible() && inst->isPositioning(LLFloaterEnums::OPEN_POSITIONING_CASCADING)) + if (inst->getVisible() + && (inst->isPositioning(LLFloaterEnums::POSITIONING_CASCADING) + || inst->isPositioning(LLFloaterEnums::POSITIONING_CASCADE_GROUP))) { if (candidate_rect.mTop > inst->getRect().mTop) { @@ -358,9 +360,7 @@ void LLFloaterReg::restoreVisibleInstances() //static std::string LLFloaterReg::getRectControlName(const std::string& name) { - std::string res = std::string("floater_rect_") + name; - LLStringUtil::replaceChar( res, ' ', '_' ); - return res; + return std::string("floater_rect_") + getBaseControlName(name); } //static @@ -368,19 +368,48 @@ std::string LLFloaterReg::declareRectControl(const std::string& name) { std::string controlname = getRectControlName(name); LLFloater::getControlGroup()->declareRect(controlname, LLRect(), - llformat("Window Position and Size for %s", name.c_str()), + llformat("Window Size for %s", name.c_str()), TRUE); return controlname; } +std::string LLFloaterReg::declarePosXControl(const std::string& name) +{ + std::string controlname = std::string("floater_pos_") + getBaseControlName(name) + "_x"; + LLFloater::getControlGroup()->declareF32(controlname, + 10.f, + llformat("Window X Position for %s", name.c_str()), + TRUE); + return controlname; +} + +std::string LLFloaterReg::declarePosYControl(const std::string& name) +{ + std::string controlname = std::string("floater_pos_") + getBaseControlName(name) + "_y"; + LLFloater::getControlGroup()->declareF32(controlname, + 10.f, + llformat("Window Y Position for %s", name.c_str()), + TRUE); + + return controlname; +} + + //static std::string LLFloaterReg::getVisibilityControlName(const std::string& name) { - std::string res = std::string("floater_vis_") + name; + return std::string("floater_vis_") + getBaseControlName(name); +} + +//static +std::string LLFloaterReg::getBaseControlName(const std::string& name) +{ + std::string res(name); LLStringUtil::replaceChar( res, ' ', '_' ); return res; } + //static std::string LLFloaterReg::declareVisibilityControl(const std::string& name) { diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 534cf8b40a..a1e1f8a988 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -115,9 +115,11 @@ public: // Control Variables static std::string getRectControlName(const std::string& name); static std::string declareRectControl(const std::string& name); + static std::string declarePosXControl(const std::string& name); + static std::string declarePosYControl(const std::string& name); static std::string getVisibilityControlName(const std::string& name); static std::string declareVisibilityControl(const std::string& name); - + static std::string getBaseControlName(const std::string& name); static std::string declareDockStateControl(const std::string& name); static std::string getDockStateControlName(const std::string& name); diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 2f1c2a47c9..4c730286da 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -36,7 +36,7 @@ #include "llcriticaldamp.h" #include "boost/foreach.hpp" -static const F32 MIN_FRACTIONAL_SIZE = 0.0001f; +static const F32 MIN_FRACTIONAL_SIZE = 0.0f; static const F32 MAX_FRACTIONAL_SIZE = 1.f; static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack"); @@ -113,7 +113,26 @@ S32 LLLayoutPanel::getLayoutDim() const ? getRect().getWidth() : getRect().getHeight())); } - + +S32 LLLayoutPanel::getTargetDim() const +{ + return mTargetDim; +} + +void LLLayoutPanel::setTargetDim(S32 value) +{ + LLRect new_rect(getRect()); + if (mOrientation == LLLayoutStack::HORIZONTAL) + { + new_rect.mRight = new_rect.mLeft + value; + } + else + { + new_rect.mTop = new_rect.mBottom + value; + } + setShape(new_rect, true); +} + S32 LLLayoutPanel::getVisibleDim() const { F32 min_dim = getRelevantMinDim(); @@ -129,6 +148,12 @@ void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientatio ? getRect().getWidth() : getRect().getHeight())); + if (mAutoResize == FALSE + && mUserResize == TRUE + && mMinDim == -1 ) + { + setMinDim(layout_dim); + } mTargetDim = llmax(layout_dim, getMinDim()); } @@ -166,12 +191,15 @@ void LLLayoutPanel::handleReshape(const LLRect& new_rect, bool by_user) LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent()); if (stackp) { - stackp->mNeedsLayout = true; if (by_user) - { - // tell layout stack to account for new shape + { // tell layout stack to account for new shape + + // make sure that panels have already been auto resized + stackp->updateLayout(); + // now apply requested size to panel stackp->updatePanelRect(this, new_rect); } + stackp->mNeedsLayout = true; } LLPanel::handleReshape(new_rect, by_user); } @@ -235,7 +263,6 @@ void LLLayoutStack::draw() drawChild(panelp, 0, 0, !clip_rect.isEmpty()); } } - mAnimatedThisFrame = false; } void LLLayoutStack::removeChild(LLView* view) @@ -304,9 +331,8 @@ void LLLayoutStack::updateLayout() if (!mNeedsLayout) return; - bool animation_in_progress = animatePanels(); + bool continue_animating = animatePanels(); F32 total_visible_fraction = 0.f; - F32 total_open_fraction = 0.f; S32 space_to_distribute = (mOrientation == HORIZONTAL) ? getRect().getWidth() : getRect().getHeight(); @@ -318,20 +344,17 @@ void LLLayoutStack::updateLayout() if (panelp->mAutoResize) { panelp->mTargetDim = panelp->getRelevantMinDim(); - if (!panelp->mCollapsed && panelp->getVisible()) - { - total_open_fraction += panelp->mFractionalSize; - } } space_to_distribute -= panelp->getVisibleDim() + llround((F32)mPanelSpacing * panelp->getVisibleAmount()); - total_visible_fraction += panelp->mFractionalSize; + total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor(); } - llassert(total_visible_fraction < 1.01f); + llassert(total_visible_fraction < 1.05f); // don't need spacing after last panel space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0; + S32 remaining_space = space_to_distribute; F32 fraction_distributed = 0.f; if (space_to_distribute > 0 && total_visible_fraction > 0.f) { // give space proportionally to visible auto resize panels @@ -343,26 +366,23 @@ void LLLayoutStack::updateLayout() S32 delta = llround((F32)space_to_distribute * fraction_to_distribute); fraction_distributed += fraction_to_distribute; panelp->mTargetDim += delta; + remaining_space -= delta; } } } - if (fraction_distributed < total_visible_fraction) - { // distribute any left over pixels to non-collapsed, visible panels - F32 fraction_left = total_visible_fraction - fraction_distributed; - S32 space_left = llround((F32)space_to_distribute * (fraction_left / total_visible_fraction)); + // distribute any left over pixels to non-collapsed, visible panels + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (remaining_space == 0) break; - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + if (panelp->mAutoResize + && !panelp->mCollapsed + && panelp->getVisible()) { - if (panelp->mAutoResize - && !panelp->mCollapsed - && panelp->getVisible()) - { - S32 space_for_panel = llmax(0, llround((F32)space_left * (panelp->mFractionalSize / total_open_fraction))); - panelp->mTargetDim += space_for_panel; - space_left -= space_for_panel; - total_open_fraction -= panelp->mFractionalSize; - } + S32 space_for_panel = remaining_space > 0 ? 1 : -1; + panelp->mTargetDim += space_for_panel; + remaining_space -= space_for_panel; } } @@ -416,7 +436,7 @@ void LLLayoutStack::updateLayout() // clear animation flag at end, since panel resizes will set it // and leave it set if there is any animation in progress - mNeedsLayout = animation_in_progress; + mNeedsLayout = continue_animating; } // end LLLayoutStack::updateLayout LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const @@ -489,38 +509,52 @@ void LLLayoutStack::updateClass() for (instance_iter it = beginInstances(); it != endInstances(); ++it) { it->updateLayout(); + it->mAnimatedThisFrame = false; } } void LLLayoutStack::updateFractionalSizes() { - F32 total_resizable_dim = 0; - S32 num_auto_resize_panels = 0; + F32 total_resizable_dim = 0.f; BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { if (panelp->mAutoResize) { total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim()); - num_auto_resize_panels++; } } - F32 total_fractional_size = 0.f; - BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { if (panelp->mAutoResize) { F32 panel_resizable_dim = llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); panelp->mFractionalSize = panel_resizable_dim > 0.f - ? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) - : MIN_FRACTIONAL_SIZE; - total_fractional_size += panelp->mFractionalSize; + ? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) + : MIN_FRACTIONAL_SIZE; llassert(!llisnan(panelp->mFractionalSize)); } } + normalizeFractionalSizes(); +} + + +void LLLayoutStack::normalizeFractionalSizes() +{ + S32 num_auto_resize_panels = 0; + F32 total_fractional_size = 0.f; + + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + total_fractional_size += panelp->mFractionalSize; + num_auto_resize_panels++; + } + } + if (total_fractional_size == 0.f) { // equal distribution BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) @@ -545,7 +579,7 @@ void LLLayoutStack::updateFractionalSizes() bool LLLayoutStack::animatePanels() { - bool animation_in_progress = false; + bool continue_animating = false; // // animate visibility @@ -565,14 +599,15 @@ bool LLLayoutStack::animatePanels() } } - animation_in_progress = true; + mAnimatedThisFrame = true; + continue_animating = true; } else { if (panelp->mVisibleAmt != 1.f) { panelp->mVisibleAmt = 1.f; - animation_in_progress = true; + mAnimatedThisFrame = true; } } } @@ -589,14 +624,15 @@ bool LLLayoutStack::animatePanels() } } - animation_in_progress = true; + continue_animating = true; + mAnimatedThisFrame = true; } else { if (panelp->mVisibleAmt != 0.f) { panelp->mVisibleAmt = 0.f; - animation_in_progress = true; + mAnimatedThisFrame = true; } } } @@ -604,22 +640,31 @@ bool LLLayoutStack::animatePanels() F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f; if (panelp->mCollapseAmt != collapse_state) { - if (!mAnimatedThisFrame) + if (mAnimate) { - panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); - } - animation_in_progress = true; + if (!mAnimatedThisFrame) + { + panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); + } - if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) + if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) + { + panelp->mCollapseAmt = collapse_state; + } + + mAnimatedThisFrame = true; + continue_animating = true; + } + else { panelp->mCollapseAmt = collapse_state; + mAnimatedThisFrame = true; } } } - mAnimatedThisFrame = true; - - return animation_in_progress; + if (mAnimatedThisFrame) mNeedsLayout = true; + return continue_animating; } void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& new_rect ) @@ -632,7 +677,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& F32 total_visible_fraction = 0.f; F32 delta_auto_resize_headroom = 0.f; - F32 total_auto_resize_headroom = 0.f; + F32 original_auto_resize_headroom = 0.f; LLLayoutPanel* other_resize_panel = NULL; LLLayoutPanel* following_panel = NULL; @@ -641,8 +686,11 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& { if (panelp->mAutoResize) { - total_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); - total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor(); + original_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); + if (panelp->getVisible() && !panelp->mCollapsed) + { + total_visible_fraction += panelp->mFractionalSize; + } } if (panelp == resized_panel) @@ -656,18 +704,25 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& } } - if (resized_panel->mAutoResize == FALSE) + + if (resized_panel->mAutoResize) { - delta_auto_resize_headroom += -delta_dim; + if (!other_resize_panel || !other_resize_panel->mAutoResize) + { + delta_auto_resize_headroom += delta_dim; + } } - if (other_resize_panel && other_resize_panel->mAutoResize == FALSE) + else { - delta_auto_resize_headroom += delta_dim; + if (!other_resize_panel || other_resize_panel->mAutoResize) + { + delta_auto_resize_headroom -= delta_dim; + } } F32 fraction_given_up = 0.f; F32 fraction_remaining = 1.f; - F32 updated_auto_resize_headroom = total_auto_resize_headroom + delta_auto_resize_headroom; + F32 updated_auto_resize_headroom = original_auto_resize_headroom + delta_auto_resize_headroom; enum { @@ -691,14 +746,15 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& case BEFORE_RESIZED_PANEL: if (panelp->mAutoResize) { // freeze current size as fraction of overall auto_resize space - F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom; + F32 fractional_adjustment_factor = updated_auto_resize_headroom == 0.f + ? 1.f + : original_auto_resize_headroom / updated_auto_resize_headroom; F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); - F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize); - fraction_given_up -= fraction_delta; + fraction_given_up -= new_fractional_size - panelp->mFractionalSize; fraction_remaining -= panelp->mFractionalSize; - panelp->mFractionalSize += fraction_delta; + panelp->mFractionalSize = new_fractional_size; llassert(!llisnan(panelp->mFractionalSize)); } else @@ -711,7 +767,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& { // freeze new size as fraction F32 new_fractional_size = (updated_auto_resize_headroom == 0.f) ? MAX_FRACTIONAL_SIZE - : llclamp((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); + : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); fraction_given_up -= new_fractional_size - panelp->mFractionalSize; fraction_remaining -= panelp->mFractionalSize; panelp->mFractionalSize = new_fractional_size; @@ -720,7 +776,6 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& else { // freeze new size as original size panelp->mTargetDim = new_dim; - fraction_remaining -= fraction_given_up; } which_panel = NEXT_PANEL; break; @@ -728,14 +783,14 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& if (panelp->mAutoResize) { fraction_remaining -= panelp->mFractionalSize; - if (fraction_given_up != 0.f) + if (resized_panel->mAutoResize) { panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); fraction_given_up = 0.f; } else { - F32 new_fractional_size = llclamp((F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) + F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); @@ -750,7 +805,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& which_panel = AFTER_RESIZED_PANEL; break; case AFTER_RESIZED_PANEL: - if (panelp->mAutoResize) + if (panelp->mAutoResize && fraction_given_up != 0.f) { panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up, MIN_FRACTIONAL_SIZE, @@ -760,6 +815,8 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& break; } } + updateLayout(); + normalizeFractionalSizes(); } void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent) diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index efe93f6def..648cd5fdce 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -72,7 +72,7 @@ public: /*virtual*/ void draw(); /*virtual*/ void removeChild(LLView*); /*virtual*/ BOOL postBuild(); - /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); + /*virtual*/ bool addChild(LLView* child, S32 tab_groupdatefractuiona = 0); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); @@ -112,6 +112,7 @@ private: LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const; LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const; void updateFractionalSizes(); + void normalizeFractionalSizes(); void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect ); S32 mPanelSpacing; @@ -154,10 +155,12 @@ public: void setVisible(BOOL visible); S32 getLayoutDim() const; - S32 getMinDim() const { return (mMinDim >= 0 || mAutoResize) ? llmax(0, mMinDim) : getLayoutDim(); } + S32 getTargetDim() const; + void setTargetDim(S32 value); + S32 getMinDim() const { return llmax(0, mMinDim); } void setMinDim(S32 value) { mMinDim = value; } - S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : mMinDim; } + S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); } void setExpandedMinDim(S32 value) { mExpandedMinDim = value; } S32 getRelevantMinDim() const diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 06dfc90d83..d0fbf4b913 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1047,7 +1047,7 @@ void LLLineEditor::cut() // Prepare for possible rollback LLLineEditorRollback rollback( this ); - gClipboard.copyFromSubstring( mText.getWString(), left_pos, length ); + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length ); deleteSelection(); // Validate new string and rollback the if needed. @@ -1078,13 +1078,13 @@ void LLLineEditor::copy() { S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromSubstring( mText.getWString(), left_pos, length ); + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length ); } } BOOL LLLineEditor::canPaste() const { - return !mReadOnly && gClipboard.canPasteString(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(); } void LLLineEditor::paste() @@ -1115,14 +1115,7 @@ void LLLineEditor::pasteHelper(bool is_primary) if (can_paste_it) { LLWString paste; - if (is_primary) - { - paste = gClipboard.getPastePrimaryWString(); - } - else - { - paste = gClipboard.getPasteWString(); - } + LLClipboard::instance().pasteFromClipboard(paste, is_primary); if (!paste.empty()) { @@ -1209,13 +1202,13 @@ void LLLineEditor::copyPrimary() { S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromPrimarySubstring( mText.getWString(), left_pos, length ); + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length, true); } } BOOL LLLineEditor::canPastePrimary() const { - return !mReadOnly && gClipboard.canPastePrimaryString(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(true); } void LLLineEditor::updatePrimary() @@ -1630,7 +1623,7 @@ void LLLineEditor::draw() LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 ); background.stretch( -mBorderThickness ); - S32 lineeditor_v_pad = llround((background.getHeight() - mGLFont->getLineHeight())/2); + S32 lineeditor_v_pad = (background.getHeight() - mGLFont->getLineHeight()) / 2; drawBackground(); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 95ecbb1c94..ff6928ffda 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -317,7 +317,7 @@ void LLMenuItemGL::setJumpKey(KEY key) // virtual U32 LLMenuItemGL::getNominalHeight( void ) const { - return llround(mFont->getLineHeight()) + MENU_ITEM_PADDING; + return mFont->getLineHeight() + MENU_ITEM_PADDING; } //virtual @@ -508,19 +508,19 @@ void LLMenuItemGL::draw( void ) { if( !mDrawBoolLabel.empty() ) { - mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, + mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } - mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, + mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); if( !mDrawAccelLabel.empty() ) { - mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, + mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } if( !mDrawBranchLabel.empty() ) { - mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, + mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color, LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } } @@ -1966,7 +1966,7 @@ void LLMenuGL::arrange( void ) // *FIX: create the item first and then ask for its dimensions? S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); // *TODO: Translate - S32 spillover_item_height = llround(LLFontGL::getFontSansSerif()->getLineHeight()) + MENU_ITEM_PADDING; + S32 spillover_item_height = LLFontGL::getFontSansSerif()->getLineHeight() + MENU_ITEM_PADDING; // Scrolling support item_list_t::iterator first_visible_item_iter; @@ -3082,7 +3082,7 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) mouse_y + MOUSE_CURSOR_PADDING, CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2, CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2); - menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect, FALSE ); + menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect ); menu->getParent()->sendChildToFront(menu); } @@ -3425,7 +3425,7 @@ void LLMenuHolderGL::draw() LLUI::pushMatrix(); { - LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom, 0.f); + LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom); selecteditem->getMenu()->drawBackground(selecteditem, interpolant); selecteditem->draw(); } diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index f3a48835b1..aa5f577897 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -349,7 +349,7 @@ void LLMultiFloater::setVisible(BOOL visible) BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask) { - if (key == 'W' && mask == (MASK_CONTROL|MASK_SHIFT)) + if (key == 'W' && mask == MASK_CONTROL) { LLFloater* floater = getActiveFloater(); // is user closeable and is system closeable diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d232e27ef2..09480968a6 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -399,6 +399,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par : mName(p.name), mType(p.type), mMessage(p.value), + mFooter(p.footer.value), mLabel(p.label), mIcon(p.icon), mURL(p.url.value), @@ -870,6 +871,16 @@ std::string LLNotification::getMessage() const return message; } +std::string LLNotification::getFooter() const +{ + if (!mTemplatep) + return std::string(); + + std::string footer = mTemplatep->mFooter; + LLStringUtil::format(footer, mSubstitutions); + return footer; +} + std::string LLNotification::getLabel() const { std::string label = mTemplatep->mLabel; @@ -1412,6 +1423,7 @@ void addPathIfExists(const std::string& new_path, std::vector<std::string>& path bool LLNotifications::loadTemplates() { + llinfos << "Reading notifications template" << llendl; std::vector<std::string> search_paths; std::string skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml"; @@ -1484,6 +1496,8 @@ bool LLNotifications::loadTemplates() mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification)); } + llinfos << "...done" << llendl; + return true; } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 462d69be2e..4ae02b943f 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -509,6 +509,7 @@ public: std::string getType() const; std::string getMessage() const; + std::string getFooter() const; std::string getLabel() const; std::string getURL() const; S32 getURLOption() const; @@ -690,7 +691,7 @@ typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap; // Abstract base class (interface) for a channel; also used for the master container. // This lets us arrange channels into a call hierarchy. -// We maintain a heirarchy of notification channels; events are always started at the top +// We maintain a hierarchy of notification channels; events are always started at the top // and propagated through the hierarchy only if they pass a filter. // Any channel can be created with a parent. A null parent (empty string) means it's // tied to the root of the tree (the LLNotifications class itself). diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index fb50c9c123..72973789db 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -167,6 +167,17 @@ struct LLNotificationTemplate {} }; + struct Footer : public LLInitParam::Block<Footer> + { + Mandatory<std::string> value; + + Footer() + : value("value") + { + addSynonym(value, ""); + } + }; + struct Params : public LLInitParam::Block<Params> { Mandatory<std::string> name; @@ -184,7 +195,8 @@ struct LLNotificationTemplate Optional<FormRef> form_ref; Optional<ENotificationPriority, NotificationPriorityValues> priority; - Multiple<Tag> tags; + Multiple<Tag> tags; + Optional<Footer> footer; Params() @@ -202,7 +214,8 @@ struct LLNotificationTemplate url("url"), unique("unique"), form_ref(""), - tags("tag") + tags("tag"), + footer("footer") {} }; @@ -231,6 +244,8 @@ struct LLNotificationTemplate // The text used to display the notification. Replaceable parameters // are enclosed in square brackets like this []. std::string mMessage; + // The text used to display the notification, but under the form. + std::string mFooter; // The label for the notification; used for // certain classes of notification (those with a window and a window title). // Also used when a notification pops up underneath the current one. diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index ad4cc20d9a..9b7e30bb04 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -378,19 +378,24 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height if (!mHideScrollbar) { - if( *visible_height < doc_height ) + // Note: 1 pixel change can happen on final animation and should not trigger + // the display of sliders. + if ((doc_height - *visible_height) > 1) { *show_v_scrollbar = TRUE; *visible_width -= scrollbar_size; } - - if( *visible_width < doc_width ) + if ((doc_width - *visible_width) > 1) { *show_h_scrollbar = TRUE; *visible_height -= scrollbar_size; + // 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 && (*visible_height < doc_height) ) + if( !*show_v_scrollbar && ((doc_height - *visible_height) > 1) ) { *show_v_scrollbar = TRUE; *visible_width -= scrollbar_size; diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index 3aa79cc255..d87c95b3d7 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -91,7 +91,7 @@ public: void setReserveScrollCorner( BOOL b ) { mReserveScrollCorner = b; } LLRect getVisibleContentRect(); LLRect getContentWindowRect(); - const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } + virtual const LLRect getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } void pageUp(S32 overlap = 0); void pageDown(S32 overlap = 0); void goToTop(); @@ -116,6 +116,9 @@ public: bool autoScroll(S32 x, S32 y); +protected: + LLView* mScrolledView; + private: // internal scrollbar handlers virtual void scrollHorizontal( S32 new_pos ); @@ -124,7 +127,6 @@ private: void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; LLScrollbar* mScrollbar[SCROLLBAR_COUNT]; - LLView* mScrolledView; S32 mSize; BOOL mIsOpaque; LLUIColor mBackgroundColor; diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 9d25c7180d..8000efad0e 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -232,7 +232,7 @@ BOOL LLScrollListText::getVisible() const //virtual S32 LLScrollListText::getHeight() const { - return llround(mFont->getLineHeight()); + return mFont->getLineHeight(); } @@ -306,7 +306,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col break; } LLRect highlight_rect(left - 2, - llround(mFont->getLineHeight()) + 1, + mFont->getLineHeight() + 1, left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1, 1); mRoundedRectImage->draw(highlight_rect, highlight_color); @@ -329,7 +329,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col break; } mFont->render(mText.getWString(), 0, - start_x, 2.f, + start_x, 0.f, display_color, mFontAlignment, LLFontGL::BOTTOM, diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 466fac33ea..b3e1b63db5 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -2504,7 +2504,7 @@ void LLScrollListCtrl::copy() { buffer += (*itor)->getContentsCSV() + "\n"; } - gClipboard.copyFromSubstring(utf8str_to_wstring(buffer), 0, buffer.length()); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(buffer), 0, buffer.length()); } // virtual diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp index d95752e31c..5a1e96ab03 100644 --- a/indra/llui/llscrolllistitem.cpp +++ b/indra/llui/llscrolllistitem.cpp @@ -138,7 +138,7 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLUI::pushMatrix(); { - LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f); + LLUI::translate((F32) cur_x, (F32) rect.mBottom); cell->draw( fg_color, highlight_color ); } diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 611df729b4..13655b5873 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -33,10 +33,10 @@ #include "v4color.h" #include "llinitparam.h" #include "llscrolllistcell.h" +#include "llcoord.h" #include <vector> -class LLCoordGL; class LLCheckBoxCtrl; class LLResizeBar; class LLScrollListCtrl; diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index ec4db14790..04cce7878e 100644 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -272,7 +272,7 @@ LLRect LLStatBar::getRequiredRect() { if (mDisplayHistory) { - rect.mTop = 67; + rect.mTop = 35 + mStatp->getNumBins(); } else { diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 0040be45c7..7aeeae298f 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1192,7 +1192,10 @@ void LLTextBase::reflow() // shrink document to minimum size (visible portion of text widget) // to force inlined widgets with follows set to shrink - mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight()); + if (mWordWrap) + { + mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight()); + } S32 cur_top = 0; @@ -2157,7 +2160,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const { // return default height rect in upper left local_rect = content_window_rect; - local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight()); + local_rect.mBottom = local_rect.mTop - mDefaultFont->getLineHeight(); return local_rect; } @@ -2380,6 +2383,9 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction) void LLTextBase::updateRects() { + LLRect old_text_rect = mVisibleTextRect; + mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect(); + if (mLineInfoList.empty()) { mTextBoundingRect = LLRect(0, mVPad, mHPad, 0); @@ -2395,10 +2401,24 @@ void LLTextBase::updateRects() } mTextBoundingRect.mTop += mVPad; - // subtract a pixel off the bottom to deal with rounding errors in measuring font height - mTextBoundingRect.mBottom -= 1; - S32 delta_pos = -mTextBoundingRect.mBottom; + S32 delta_pos = 0; + + switch(mVAlign) + { + case LLFontGL::TOP: + delta_pos = llmax(mVisibleTextRect.getHeight() - mTextBoundingRect.mTop, -mTextBoundingRect.mBottom); + break; + case LLFontGL::VCENTER: + delta_pos = (llmax(mVisibleTextRect.getHeight() - mTextBoundingRect.mTop, -mTextBoundingRect.mBottom) + (mVisibleTextRect.mBottom - mTextBoundingRect.mBottom)) / 2; + break; + case LLFontGL::BOTTOM: + delta_pos = mVisibleTextRect.mBottom - mTextBoundingRect.mBottom; + break; + case LLFontGL::BASELINE: + // do nothing + break; + } // move line segments to fit new document rect for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it) { @@ -2408,8 +2428,9 @@ void LLTextBase::updateRects() } // update document container dimensions according to text contents - LLRect doc_rect = mTextBoundingRect; + LLRect doc_rect; // use old mVisibleTextRect constraint document to width of viewable region + doc_rect.mBottom = llmin(mVisibleTextRect.mBottom, mTextBoundingRect.mBottom); doc_rect.mLeft = 0; // allow horizontal scrolling? @@ -2419,11 +2440,22 @@ void LLTextBase::updateRects() doc_rect.mRight = mScroller ? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight) : mVisibleTextRect.getWidth(); + doc_rect.mTop = llmax(mVisibleTextRect.mTop, mTextBoundingRect.mTop); if (!mScroller) { // push doc rect to top of text widget - doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop); + switch(mVAlign) + { + case LLFontGL::TOP: + doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop); + break; + case LLFontGL::VCENTER: + doc_rect.translate(0, (mVisibleTextRect.getHeight() - doc_rect.mTop) / 2); + case LLFontGL::BOTTOM: + default: + break; + } } mDocumentView->setShape(doc_rect); @@ -2431,7 +2463,6 @@ void LLTextBase::updateRects() //update mVisibleTextRect *after* mDocumentView has been resized // so that scrollbars are added if document needs to scroll // since mVisibleTextRect does not include scrollbars - LLRect old_text_rect = mVisibleTextRect; mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect(); //FIXME: replace border with image? if (mBorderVisible) @@ -2444,9 +2475,27 @@ void LLTextBase::updateRects() } // update document container again, using new mVisibleTextRect (that has scrollbars enabled as needed) + doc_rect.mBottom = llmin(mVisibleTextRect.mBottom, mTextBoundingRect.mBottom); + doc_rect.mLeft = 0; doc_rect.mRight = mScroller ? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight) : mVisibleTextRect.getWidth(); + doc_rect.mTop = llmax(mVisibleTextRect.mTop, mTextBoundingRect.mTop); + if (!mScroller) + { + // push doc rect to top of text widget + switch(mVAlign) + { + case LLFontGL::TOP: + doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop); + break; + case LLFontGL::VCENTER: + doc_rect.translate(0, (mVisibleTextRect.getHeight() - doc_rect.mTop) / 2); + case LLFontGL::BOTTOM: + default: + break; + } + } mDocumentView->setShape(doc_rect); } @@ -2560,8 +2609,7 @@ BOOL LLTextSegment::handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; BOOL LLTextSegment::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; } const std::string& LLTextSegment::getName() const { - static std::string empty_string(""); - return empty_string; + return LLStringUtil::null; } void LLTextSegment::onMouseCaptureLost() {} void LLTextSegment::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {} @@ -2578,7 +2626,7 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e mToken(NULL), mEditor(editor) { - mFontHeight = llceil(mStyle->getFont()->getLineHeight()); + mFontHeight = mStyle->getFont()->getLineHeight(); LLUIImagePtr image = mStyle->getImage(); if (image.notNull()) @@ -2594,7 +2642,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 { mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color)); - mFontHeight = llceil(mStyle->getFont()->getLineHeight()); + mFontHeight = mStyle->getFont()->getLineHeight(); } LLNormalTextSegment::~LLNormalTextSegment() @@ -2962,11 +3010,11 @@ LLLineBreakTextSegment::LLLineBreakTextSegment(S32 pos):LLTextSegment(pos,pos+1) { LLStyleSP s( new LLStyle(LLStyle::Params().visible(true))); - mFontHeight = llceil(s->getFont()->getLineHeight()); + mFontHeight = s->getFont()->getLineHeight(); } LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1) { - mFontHeight = llceil(style->getFont()->getLineHeight()); + mFontHeight = style->getFont()->getLineHeight(); } LLLineBreakTextSegment::~LLLineBreakTextSegment() { @@ -3003,7 +3051,7 @@ static const S32 IMAGE_HPAD = 3; bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { width = 0; - height = llceil(mStyle->getFont()->getLineHeight());; + height = mStyle->getFont()->getLineHeight(); LLUIImagePtr image = mStyle->getImage(); if( num_chars>0 && image.notNull()) diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3a23ce1cac..9720dded6c 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1332,7 +1332,7 @@ void LLTextEditor::cut() } S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromSubstring( getWText(), left_pos, length, mSourceID ); + LLClipboard::instance().copyToClipboard( getWText(), left_pos, length); deleteSelection( FALSE ); onKeyStroke(); @@ -1352,12 +1352,12 @@ void LLTextEditor::copy() } S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromSubstring(getWText(), left_pos, length, mSourceID); + LLClipboard::instance().copyToClipboard(getWText(), left_pos, length); } BOOL LLTextEditor::canPaste() const { - return !mReadOnly && gClipboard.canPasteString(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(); } // paste from clipboard @@ -1393,16 +1393,8 @@ void LLTextEditor::pasteHelper(bool is_primary) return; } - LLUUID source_id; LLWString paste; - if (is_primary) - { - paste = gClipboard.getPastePrimaryWString(&source_id); - } - else - { - paste = gClipboard.getPasteWString(&source_id); - } + LLClipboard::instance().pasteFromClipboard(paste, is_primary); if (paste.empty()) { @@ -1475,12 +1467,12 @@ void LLTextEditor::copyPrimary() } S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromPrimarySubstring(getWText(), left_pos, length, mSourceID); + LLClipboard::instance().copyToClipboard(getWText(), left_pos, length, true); } BOOL LLTextEditor::canPastePrimary() const { - return !mReadOnly && gClipboard.canPastePrimaryString(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(true); } void LLTextEditor::updatePrimary() @@ -1992,7 +1984,7 @@ void LLTextEditor::drawPreeditMarker() return; } - const S32 line_height = llround( mDefaultFont->getLineHeight() ); + const S32 line_height = mDefaultFont->getLineHeight(); S32 line_start = getLineStart(cur_line); S32 line_y = mVisibleTextRect.mTop - line_height; @@ -2715,7 +2707,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect const LLWString textString(getWText()); const llwchar * const text = textString.c_str(); - const S32 line_height = llround(mDefaultFont->getLineHeight()); + const S32 line_height = mDefaultFont->getLineHeight(); if (coord) { @@ -2818,7 +2810,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length) S32 LLTextEditor::getPreeditFontSize() const { - return llround(mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround((F32)mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); } BOOL LLTextEditor::isDirty() const diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 9b31a6449d..81ea0ebf0c 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -827,7 +827,7 @@ void LLToolBar::draw() // rect may have shifted during layout LLUI::popMatrix(); LLUI::pushMatrix(); - LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom, 0.f); + LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); // Position the caret LLIconCtrl* caret = getChild<LLIconCtrl>("caret"); diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 23cdd9ad9a..f737d48abf 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -180,6 +180,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) params.font = p.font; params.use_ellipses = true; params.wrap = p.wrap; + params.font_valign = LLFontGL::VCENTER; params.parse_urls = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips mTextBox = LLUICtrlFactory::create<LLTextBox> (params); addChild(mTextBox); @@ -190,7 +191,6 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) { LLButton::Params icon_params; icon_params.name = "tooltip_info"; - icon_params.label(""); // provid label but set to empty so name does not overwrite it -angela LLRect icon_rect; LLUIImage* imagep = p.image; TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16); @@ -291,6 +291,12 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth()); S32 text_height = mTextBox->getTextPixelHeight(); mTextBox->reshape(text_width, text_height); + if (mInfoButton) + { + LLRect text_rect = mTextBox->getRect(); + LLRect icon_rect = mInfoButton->getRect(); + mTextBox->translate(0, icon_rect.getCenterY() - text_rect.getCenterY()); + } // reshape tooltip panel to fit text box LLRect tooltip_rect = calcBoundingRect(); @@ -299,6 +305,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) tooltip_rect.mBottom = 0; tooltip_rect.mLeft = 0; + mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding)); + setShape(tooltip_rect); } diff --git a/indra/llxuixml/lltrans.cpp b/indra/llui/lltrans.cpp index 5388069c24..5388069c24 100644 --- a/indra/llxuixml/lltrans.cpp +++ b/indra/llui/lltrans.cpp diff --git a/indra/llxuixml/lltrans.h b/indra/llui/lltrans.h index 128b51d383..128b51d383 100644 --- a/indra/llxuixml/lltrans.h +++ b/indra/llui/lltrans.h diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 6b74c5a6be..b5e27616b7 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -972,43 +972,53 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor // Draw gray and white checkerboard with black border void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha) { - // Initialize the first time this is called. - const S32 PIXELS = 32; - static GLubyte checkerboard[PIXELS * PIXELS]; - static BOOL first = TRUE; - if( first ) - { - for( S32 i = 0; i < PIXELS; i++ ) + if (!LLGLSLShader::sNoFixedFunction) + { + // Initialize the first time this is called. + const S32 PIXELS = 32; + static GLubyte checkerboard[PIXELS * PIXELS]; + static BOOL first = TRUE; + if( first ) { - for( S32 j = 0; j < PIXELS; j++ ) + for( S32 i = 0; i < PIXELS; i++ ) { - checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; + for( S32 j = 0; j < PIXELS; j++ ) + { + checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; + } } + first = FALSE; } - first = FALSE; - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - // ...white squares - gGL.color4f( 1.f, 1.f, 1.f, alpha ); - gl_rect_2d(rect); + // ...white squares + gGL.color4f( 1.f, 1.f, 1.f, alpha ); + gl_rect_2d(rect); - // ...gray squares - gGL.color4f( .7f, .7f, .7f, alpha ); - gGL.flush(); + // ...gray squares + gGL.color4f( .7f, .7f, .7f, alpha ); + gGL.flush(); - if (!LLGLSLShader::sNoFixedFunction) - { //polygon stipple is deprecated glPolygonStipple( checkerboard ); LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE); gl_rect_2d(rect); } else - { - gl_rect_2d(rect); + { //polygon stipple is deprecated, use "Checker" texture + LLPointer<LLUIImage> img = LLUI::getUIImage("Checker"); + gGL.getTexUnit(0)->bind(img->getImage()); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + + LLColor4 color(1.f, 1.f, 1.f, alpha); + LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); + + gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), + img->getImage(), color, uv_rect); } + gGL.flush(); } @@ -1688,21 +1698,22 @@ void LLUI::translate(F32 x, F32 y, F32 z) gGL.translateUI(x,y,z); LLFontGL::sCurOrigin.mX += (S32) x; LLFontGL::sCurOrigin.mY += (S32) y; - LLFontGL::sCurOrigin.mZ += z; + LLFontGL::sCurDepth += z; } //static void LLUI::pushMatrix() { gGL.pushUIMatrix(); - LLFontGL::sOriginStack.push_back(LLFontGL::sCurOrigin); + LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth)); } //static void LLUI::popMatrix() { gGL.popUIMatrix(); - LLFontGL::sCurOrigin = *LLFontGL::sOriginStack.rbegin(); + LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first; + LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second; LLFontGL::sOriginStack.pop_back(); } @@ -1712,7 +1723,7 @@ void LLUI::loadIdentity() gGL.loadUIIdentity(); LLFontGL::sCurOrigin.mX = 0; LLFontGL::sCurOrigin.mY = 0; - LLFontGL::sCurOrigin.mZ = 0; + LLFontGL::sCurDepth = 0.f; } //static @@ -1735,10 +1746,7 @@ void LLUI::setMousePositionScreen(S32 x, S32 y) screen_x = llround((F32)x * sGLScaleFactor.mV[VX]); screen_y = llround((F32)y * sGLScaleFactor.mV[VY]); - LLCoordWindow window_point; - LLView::getWindow()->convertCoords(LLCoordGL(screen_x, screen_y), &window_point); - - LLView::getWindow()->setCursorPosition(window_point); + LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert()); } //static @@ -1746,8 +1754,7 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y) { LLCoordWindow cursor_pos_window; getWindow()->getCursorPosition(&cursor_pos_window); - LLCoordGL cursor_pos_gl; - getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); + LLCoordGL cursor_pos_gl(cursor_pos_window.convert()); *x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]); *y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]); } @@ -2052,7 +2059,7 @@ void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y) // Start at spawn position (using left/top) view->setOrigin( local_x, local_y - view->getRect().getHeight()); // Make sure we're on-screen and not overlapping the mouse - view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE ); + view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect ); } LLView* LLUI::resolvePath(LLView* context, const std::string& path) diff --git a/indra/llxuixml/lluicolor.cpp b/indra/llui/lluicolor.cpp index f9bb80f8c5..f9bb80f8c5 100644 --- a/indra/llxuixml/lluicolor.cpp +++ b/indra/llui/lluicolor.cpp diff --git a/indra/llxuixml/lluicolor.h b/indra/llui/lluicolor.h index 97ebea854a..97ebea854a 100644 --- a/indra/llxuixml/lluicolor.h +++ b/indra/llui/lluicolor.h diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index ac69d3bf85..c4e073ccdb 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -128,17 +128,13 @@ void LLUIString::updateResult() const } mResult = mOrig; - // get the defailt args + local args - if (!mArgs || mArgs->empty()) + // get the default args + local args + LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs(); + if (mArgs && !mArgs->empty()) { - LLStringUtil::format(mResult, LLTrans::getDefaultArgs()); - } - else - { - LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs(); combined_args.insert(mArgs->begin(), mArgs->end()); - LLStringUtil::format(mResult, combined_args); } + LLStringUtil::format(mResult, combined_args); } void LLUIString::updateWResult() const diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index e1ee0a5b14..54843227b7 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1106,7 +1106,7 @@ void LLView::drawChildren() { LLUI::pushMatrix(); { - LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); + LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom); // flag the fact we are in draw here, in case overridden draw() method attempts to remove this widget viewp->mInDraw = true; viewp->draw(); @@ -1159,7 +1159,7 @@ void LLView::drawDebugRect() if (getUseBoundingRect()) { - LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom, 0.f); + LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom); } LLRect debug_rect = getUseBoundingRect() ? mBoundingRect : mRect; @@ -1231,7 +1231,7 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr gGL.matrixMode(LLRender::MM_MODELVIEW); LLUI::pushMatrix(); { - LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset, 0.f); + LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset); childp->draw(); } LLUI::popMatrix(); @@ -1300,7 +1300,10 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent) S32 delta_x = child_rect.mLeft - viewp->getRect().mLeft; S32 delta_y = child_rect.mBottom - viewp->getRect().mBottom; viewp->translate( delta_x, delta_y ); - viewp->reshape(child_rect.getWidth(), child_rect.getHeight()); + if (child_rect.getWidth() != viewp->getRect().getWidth() || child_rect.getHeight() != viewp->getRect().getHeight()) + { + viewp->reshape(child_rect.getWidth(), child_rect.getHeight()); + } } } @@ -1616,59 +1619,30 @@ LLView* LLView::findNextSibling(LLView* child) } -LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside) +LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, S32 min_overlap_pixels) { LLCoordGL delta; - if (allow_partial_outside) - { - const S32 KEEP_ONSCREEN_PIXELS = 16; + const S32 KEEP_ONSCREEN_PIXELS_WIDTH = llmin(min_overlap_pixels, input.getWidth()); + const S32 KEEP_ONSCREEN_PIXELS_HEIGHT = llmin(min_overlap_pixels, input.getHeight()); - if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft ) - { - delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS); - } - else - if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight ) - { - delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS); - } + if( input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH < constraint.mLeft ) + { + delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH); + } + else if( input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH > constraint.mRight ) + { + delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH); + } - if( input.mTop > constraint.mTop ) - { - delta.mY = constraint.mTop - input.mTop; - } - else - if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom ) - { - delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS); - } + if( input.mTop > constraint.mTop ) + { + delta.mY = constraint.mTop - input.mTop; } else + if( input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT < constraint.mBottom ) { - if( input.mLeft < constraint.mLeft ) - { - delta.mX = constraint.mLeft - input.mLeft; - } - else - if( input.mRight > constraint.mRight ) - { - delta.mX = constraint.mRight - input.mRight; - // compensate for left edge possible going off screen - delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() ); - } - - if( input.mTop > constraint.mTop ) - { - delta.mY = constraint.mTop - input.mTop; - } - else - if( input.mBottom < constraint.mBottom ) - { - delta.mY = constraint.mBottom - input.mBottom; - // compensate for top edge possible going off screen - delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() ); - } + delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT); } return delta; @@ -1677,9 +1651,9 @@ LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BO // Moves the view so that it is entirely inside of constraint. // If the view will not fit because it's too big, aligns with the top and left. // (Why top and left? That's where the drag bars are for floaters.) -BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside ) +BOOL LLView::translateIntoRect(const LLRect& constraint, S32 min_overlap_pixels) { - LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside); + LLCoordGL translation = getNeededTranslation(getRect(), constraint, min_overlap_pixels); if (translation.mX != 0 || translation.mY != 0) { @@ -1691,9 +1665,9 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs // move this view into "inside" but not onto "exclude" // NOTE: if this view is already contained in "inside", we ignore the "exclude" rect -BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside ) +BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels) { - LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside); + LLCoordGL translation = getNeededTranslation(getRect(), inside, min_overlap_pixels); if (translation.mX != 0 || translation.mY != 0) { @@ -1861,7 +1835,10 @@ const LLCtrlQuery & LLView::getFocusRootsQuery() void LLView::setShape(const LLRect& new_rect, bool by_user) { - handleReshape(new_rect, by_user); + if (new_rect != getRect()) + { + handleReshape(new_rect, by_user); + } } void LLView::handleReshape(const LLRect& new_rect, bool by_user) @@ -2251,145 +2228,163 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect) } //static -void LLView::applyXUILayout(LLView::Params& p, LLView* parent) +void LLView::applyXUILayout(LLView::Params& p, LLView* parent, LLRect layout_rect) { + if (!parent) return; + const S32 VPAD = 4; const S32 MIN_WIDGET_HEIGHT = 10; // *NOTE: This will confuse export of floater/panel coordinates unless // the default is also "topleft". JC - if (p.layout().empty() && parent) + if (p.layout().empty()) { p.layout = parent->getLayout(); } - if (parent) + if (layout_rect.isEmpty()) { - LLRect parent_rect = parent->getLocalRect(); - // overwrite uninitialized rect params, using context - LLRect default_rect = parent->getLocalRect(); + layout_rect = parent->getLocalRect(); + } - bool layout_topleft = (p.layout() == "topleft"); + // overwrite uninitialized rect params, using context + LLRect default_rect = parent->getLocalRect(); - // convert negative or centered coordinates to parent relative values - // Note: some of this logic matches the logic in TypedParam<LLRect>::setValueFromBlock() - if (p.rect.left.isProvided() && p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); - if (p.rect.right.isProvided() && p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); - if (p.rect.bottom.isProvided() && p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); - if (p.rect.top.isProvided() && p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); + bool layout_topleft = (p.layout() == "topleft"); + // convert negative or centered coordinates to parent relative values + // Note: some of this logic matches the logic in TypedParam<LLRect>::setValueFromBlock() + if (p.rect.left.isProvided()) + { + p.rect.left = p.rect.left + ((p.rect.left >= 0) ? layout_rect.mLeft : layout_rect.mRight); + } + if (p.rect.right.isProvided()) + { + p.rect.right = p.rect.right + ((p.rect.right >= 0) ? layout_rect.mLeft : layout_rect.mRight); + } + if (p.rect.bottom.isProvided()) + { + p.rect.bottom = p.rect.bottom + ((p.rect.bottom >= 0) ? layout_rect.mBottom : layout_rect.mTop); if (layout_topleft) { //invert top to bottom - if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top; - if (p.rect.bottom.isProvided()) p.rect.bottom = parent_rect.getHeight() - p.rect.bottom; + p.rect.bottom = layout_rect.mBottom + layout_rect.mTop - p.rect.bottom; } - - // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels - if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0) + } + if (p.rect.top.isProvided()) + { + p.rect.top = p.rect.top + ((p.rect.top >= 0) ? layout_rect.mBottom : layout_rect.mTop); + if (layout_topleft) { - p.rect.height = MIN_WIDGET_HEIGHT; + //invert top to bottom + p.rect.top = layout_rect.mBottom + layout_rect.mTop - p.rect.top; } + } + + // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels + if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0) + { + p.rect.height = MIN_WIDGET_HEIGHT; + } - default_rect.translate(0, default_rect.getHeight()); + default_rect.translate(0, default_rect.getHeight()); - // If there was a recently constructed child, use its rectangle - get_last_child_rect(parent, &default_rect); + // If there was a recently constructed child, use its rectangle + get_last_child_rect(parent, &default_rect); - if (layout_topleft) + if (layout_topleft) + { + // Invert the sense of bottom_delta for topleft layout + if (p.bottom_delta.isProvided()) { - // Invert the sense of bottom_delta for topleft layout - if (p.bottom_delta.isProvided()) - { - p.bottom_delta = -p.bottom_delta; - } - else if (p.top_pad.isProvided()) - { - p.bottom_delta = -(p.rect.height + p.top_pad); - } - else if (p.top_delta.isProvided()) - { - p.bottom_delta = - -(p.top_delta + p.rect.height - default_rect.getHeight()); - } - else if (!p.left_delta.isProvided() - && !p.left_pad.isProvided()) - { - // set default position is just below last rect - p.bottom_delta.set(-(p.rect.height + VPAD), false); - } - else - { - p.bottom_delta.set(0, false); - } - - // default to same left edge - if (!p.left_delta.isProvided()) - { - p.left_delta.set(0, false); - } - if (p.left_pad.isProvided()) - { - // left_pad is based on prior widget's right edge - p.left_delta.set(p.left_pad + default_rect.getWidth(), false); - } - - default_rect.translate(p.left_delta, p.bottom_delta); + p.bottom_delta = -p.bottom_delta; } - else - { - // set default position is just below last rect - if (!p.bottom_delta.isProvided()) - { - p.bottom_delta.set(-(p.rect.height + VPAD), false); - } - if (!p.left_delta.isProvided()) - { - p.left_delta.set(0, false); - } - default_rect.translate(p.left_delta, p.bottom_delta); + else if (p.top_pad.isProvided()) + { + p.bottom_delta = -(p.rect.height + p.top_pad); } - - // this handles case where *both* x and x_delta are provided - // ignore x in favor of default x + x_delta - if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false); - if (p.left_delta.isProvided()) p.rect.left.set(0, false); - - // selectively apply rectangle defaults, making sure that - // params are not flagged as having been "provided" - // as rect params are overconstrained and rely on provided flags - if (!p.rect.left.isProvided()) + else if (p.top_delta.isProvided()) { - p.rect.left.set(default_rect.mLeft, false); - //HACK: get around the fact that setting a rect param component value won't invalidate the existing rect object value - p.rect.paramChanged(p.rect.left, true); + p.bottom_delta = + -(p.top_delta + p.rect.height - default_rect.getHeight()); } - if (!p.rect.bottom.isProvided()) + else if (!p.left_delta.isProvided() + && !p.left_pad.isProvided()) { - p.rect.bottom.set(default_rect.mBottom, false); - p.rect.paramChanged(p.rect.bottom, true); + // set default position is just below last rect + p.bottom_delta.set(-(p.rect.height + VPAD), false); } - if (!p.rect.top.isProvided()) + else { - p.rect.top.set(default_rect.mTop, false); - p.rect.paramChanged(p.rect.top, true); + p.bottom_delta.set(0, false); } - if (!p.rect.right.isProvided()) + + // default to same left edge + if (!p.left_delta.isProvided()) { - p.rect.right.set(default_rect.mRight, false); - p.rect.paramChanged(p.rect.right, true); - + p.left_delta.set(0, false); } - if (!p.rect.width.isProvided()) + if (p.left_pad.isProvided()) { - p.rect.width.set(default_rect.getWidth(), false); - p.rect.paramChanged(p.rect.width, true); + // left_pad is based on prior widget's right edge + p.left_delta.set(p.left_pad + default_rect.getWidth(), false); } - if (!p.rect.height.isProvided()) + + default_rect.translate(p.left_delta, p.bottom_delta); + } + else + { + // set default position is just below last rect + if (!p.bottom_delta.isProvided()) + { + p.bottom_delta.set(-(p.rect.height + VPAD), false); + } + if (!p.left_delta.isProvided()) { - p.rect.height.set(default_rect.getHeight(), false); - p.rect.paramChanged(p.rect.height, true); + p.left_delta.set(0, false); } + default_rect.translate(p.left_delta, p.bottom_delta); + } + + // this handles case where *both* x and x_delta are provided + // ignore x in favor of default x + x_delta + if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false); + if (p.left_delta.isProvided()) p.rect.left.set(0, false); + + // selectively apply rectangle defaults, making sure that + // params are not flagged as having been "provided" + // as rect params are overconstrained and rely on provided flags + if (!p.rect.left.isProvided()) + { + p.rect.left.set(default_rect.mLeft, false); + //HACK: get around the fact that setting a rect param component value won't invalidate the existing rect object value + p.rect.paramChanged(p.rect.left, true); + } + if (!p.rect.bottom.isProvided()) + { + p.rect.bottom.set(default_rect.mBottom, false); + p.rect.paramChanged(p.rect.bottom, true); + } + if (!p.rect.top.isProvided()) + { + p.rect.top.set(default_rect.mTop, false); + p.rect.paramChanged(p.rect.top, true); + } + if (!p.rect.right.isProvided()) + { + p.rect.right.set(default_rect.mRight, false); + p.rect.paramChanged(p.rect.right, true); + + } + if (!p.rect.width.isProvided()) + { + p.rect.width.set(default_rect.getWidth(), false); + p.rect.paramChanged(p.rect.width, true); + } + if (!p.rect.height.isProvided()) + { + p.rect.height.set(default_rect.getHeight(), false); + p.rect.paramChanged(p.rect.height, true); } } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index f1fac5f69c..1c35349510 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -370,8 +370,8 @@ public: virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual void translate( S32 x, S32 y ); void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); } - BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside ); - BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside ); + BOOL translateIntoRect( const LLRect& constraint, S32 min_overlap_pixels = S32_MAX); + BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels = S32_MAX); void centerWithin(const LLRect& bounds); void setShape(const LLRect& new_rect, bool by_user = false); @@ -505,7 +505,7 @@ public: // Set up params after XML load before calling new(), // usually to adjust layout. - static void applyXUILayout(Params& p, LLView* parent); + static void applyXUILayout(Params& p, LLView* parent, LLRect layout_rect = LLRect()); // For re-export of floaters and panels, convert the coordinate system // to be top-left based. diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llui/llxuiparser.cpp index afc76024d1..afc76024d1 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llui/llxuiparser.cpp diff --git a/indra/llxuixml/llxuiparser.h b/indra/llui/llxuiparser.h index d7cd256967..d7cd256967 100644 --- a/indra/llxuixml/llxuiparser.h +++ b/indra/llui/llxuiparser.h diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index c75df86891..cb3b7abb14 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -105,28 +105,6 @@ LLStyle::Params::Params() namespace LLInitParam { - Param::Param(BaseBlock* enclosing_block) - : mIsProvided(false) - { - const U8* my_addr = reinterpret_cast<const U8*>(this); - const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); - mEnclosingBlockOffset = (U16)(my_addr - block_addr); - } - - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} - void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} - param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} - - void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) - { - descriptor.mCurrentBlockPtr = this; - } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; } - void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const {} - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_value, S32 max_value) const { return true; } - bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } - bool BaseBlock::validateBlock(bool emit_errors) const { return true; } - ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) : super_t(color) {} diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index c1fb050206..8f0a48018f 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -70,21 +70,6 @@ S32 LLUIImage::getHeight() const return 0; } -namespace LLInitParam -{ - BlockDescriptor::BlockDescriptor() {} - ParamDescriptor::ParamDescriptor(param_handle_t p, - merge_func_t merge_func, - deserialize_func_t deserialize_func, - serialize_func_t serialize_func, - validation_func_t validation_func, - inspect_func_t inspect_func, - S32 min_count, - S32 max_count){} - ParamDescriptor::~ParamDescriptor() {} - -} - namespace tut { struct LLUrlEntryData diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 7183413463..963473c92a 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -63,40 +63,6 @@ S32 LLUIImage::getHeight() const namespace LLInitParam { - BlockDescriptor::BlockDescriptor() {} - ParamDescriptor::ParamDescriptor(param_handle_t p, - merge_func_t merge_func, - deserialize_func_t deserialize_func, - serialize_func_t serialize_func, - validation_func_t validation_func, - inspect_func_t inspect_func, - S32 min_count, - S32 max_count){} - ParamDescriptor::~ParamDescriptor() {} - - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} - param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} - void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} - - void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) - { - descriptor.mCurrentBlockPtr = this; - } - - Param::Param(BaseBlock* enclosing_block) - : mIsProvided(false) - { - const U8* my_addr = reinterpret_cast<const U8*>(this); - const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); - mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr)); - } - - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; } - void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const {} - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const { return true; } - bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } - bool BaseBlock::validateBlock(bool emit_errors) const { return true; } - ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) : super_t(color) {} diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index f3ac17d612..32d081d552 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -86,6 +86,13 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) std::string fullpath; S32 result; + // File masks starting with "/" will match nothing, so we consider them invalid. + if (LLStringUtil::startsWith(mask, getDirDelimiter())) + { + llwarns << "Invalid file mask: " << mask << llendl; + llassert(!"Invalid file mask"); + } + LLDirIterator iter(dirname, mask); while (iter.next(filename)) { diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp index 3d3ed9f6d4..073b1af2a1 100644 --- a/indra/llvfs/lllfsthread.cpp +++ b/indra/llvfs/lllfsthread.cpp @@ -45,7 +45,7 @@ void LLLFSThread::initClass(bool local_is_threaded) //static S32 LLLFSThread::updateClass(U32 ms_elapsed) { - sLocal->update(ms_elapsed); + sLocal->update((F32)ms_elapsed); return sLocal->getPending(); } diff --git a/indra/llvfs/llvfsthread.cpp b/indra/llvfs/llvfsthread.cpp index 254f8b55ba..a57e2b15ab 100644 --- a/indra/llvfs/llvfsthread.cpp +++ b/indra/llvfs/llvfsthread.cpp @@ -46,7 +46,7 @@ void LLVFSThread::initClass(bool local_is_threaded) //static S32 LLVFSThread::updateClass(U32 ms_elapsed) { - sLocal->update(ms_elapsed); + sLocal->update((F32)ms_elapsed); return sLocal->getPending(); } diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index d4d444eb28..15acddd987 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -124,10 +124,9 @@ class LLDragDropWin32Target: ScreenToClient( mAppWindowHandle, &pt2 ); LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); MASK mask = gKeyboard->currentMask(TRUE); - LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask, LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl ); switch (result) @@ -180,10 +179,9 @@ class LLDragDropWin32Target: ScreenToClient( mAppWindowHandle, &pt2 ); LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); MASK mask = gKeyboard->currentMask(TRUE); - LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask, LLWindowCallbacks::DNDA_TRACK, mDropUrl ); switch (result) @@ -237,15 +235,13 @@ class LLDragDropWin32Target: LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); if ( NULL != window_imp ) { - LLCoordGL gl_coord( 0, 0 ); - POINT pt_client; pt_client.x = pt.x; pt_client.y = pt.y; ScreenToClient( mAppWindowHandle, &pt_client ); LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); - window_imp->convertCoords(cursor_coord_window, &gl_coord); + LLCoordGL gl_coord(cursor_coord_window.convert()); llinfos << "### (Drop) URL is: " << mDropUrl << llendl; llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl; diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 2e9e31bfea..5b7424acbb 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -192,6 +192,21 @@ BOOL LLWindow::setSize(LLCoordScreen size) return setSizeImpl(size); } +BOOL LLWindow::setSize(LLCoordWindow size) +{ + //HACK: we are inconsistently using minimum window dimensions + // in this case, we are constraining the inner "client" rect and other times + // we constrain the outer "window" rect + // There doesn't seem to be a good way to do this consistently without a bunch of platform + // specific code + if (!getMaximized()) + { + size.mX = llmax(size.mX, mMinWindowWidth); + size.mY = llmax(size.mY, mMinWindowHeight); + } + return setSizeImpl(size); +} + // virtual void LLWindow::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately) @@ -436,3 +451,42 @@ BOOL LLWindowManager::isWindowValid(LLWindow *window) { return sWindowList.find(window) != sWindowList.end(); } + +//coordinate conversion utility funcs that forward to llwindow +LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const +{ + const LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this); + + LLWindow* windowp = &(*LLWindow::beginInstances()); + LLCoordGL out; + windowp->convertCoords(self, &out); + return out.convert(); +} + +void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from) +{ + LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this); + + LLWindow* windowp = &(*LLWindow::beginInstances()); + LLCoordGL from_gl(from); + windowp->convertCoords(from_gl, &self); +} + +LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const +{ + const LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this); + + LLWindow* windowp = &(*LLWindow::beginInstances()); + LLCoordGL out; + windowp->convertCoords(self, &out); + return out.convert(); +} + +void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from) +{ + LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this); + + LLWindow* windowp = &(*LLWindow::beginInstances()); + LLCoordGL from_gl(from); + windowp->convertCoords(from_gl, &self); +} diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index cab2d0a8fb..4da87f4e06 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -39,7 +39,7 @@ class LLWindowCallbacks; // Refer to llwindow_test in test/common/llwindow for usage example -class LLWindow +class LLWindow : public LLInstanceTracker<LLWindow> { public: struct LLWindowResolution @@ -73,6 +73,7 @@ public: virtual BOOL getSize(LLCoordWindow *size) = 0; virtual BOOL setPosition(LLCoordScreen position) = 0; BOOL setSize(LLCoordScreen size); + BOOL setSize(LLCoordWindow size); virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true); virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) = 0; virtual BOOL setCursorPosition(LLCoordWindow position) = 0; @@ -172,6 +173,7 @@ protected: virtual BOOL canDelete(); virtual BOOL setSizeImpl(LLCoordScreen size) = 0; + virtual BOOL setSizeImpl(LLCoordWindow size) = 0; protected: LLWindowCallbacks* mCallbacks; diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index c2705bbf74..9712ae1d91 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -28,8 +28,6 @@ #include "llwindowcallbacks.h" -#include "llcoord.h" - // // LLWindowCallbacks // diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 8572b442f1..7da5959700 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -26,7 +26,7 @@ #ifndef LLWINDOWCALLBACKS_H #define LLWINDOWCALLBACKS_H -class LLCoordGL; +#include "llcoord.h" class LLWindow; class LLWindowCallbacks diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index d4a778cb85..1f767f4c97 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -47,6 +47,7 @@ public: /*virtual*/ BOOL getSize(LLCoordWindow *size) {return FALSE;}; /*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;}; + /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;}; /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;}; /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index c952f8bbcf..32bb84cba5 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1266,6 +1266,31 @@ BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size) return TRUE; } +BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size) +{ + Rect client_rect; + if (mWindow) + { + OSStatus err = GetWindowBounds(mWindow, kWindowContentRgn, &client_rect); + if (err == noErr) + { + client_rect.right = client_rect.left + size.mX; + client_rect.bottom = client_rect.top + size.mY; + err = SetWindowBounds(mWindow, kWindowContentRgn, &client_rect); + } + if (err == noErr) + { + return TRUE; + } + else + { + llinfos << "Error setting size" << err << llendl; + return FALSE; + } + } + return FALSE; +} + void LLWindowMacOSX::swapBuffers() { aglSwapBuffers(mContext); diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 073f294b54..52ba8b3bf3 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -59,6 +59,7 @@ public: /*virtual*/ BOOL getSize(LLCoordWindow *size); /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); + /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 5f5baceef8..3d33af9d9b 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -981,6 +981,25 @@ BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size) return FALSE; } +BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size) +{ + if(mWindow) + { + // Push a resize event onto SDL's queue - we'll handle it + // when it comes out again. + SDL_Event event; + event.type = SDL_VIDEORESIZE; + event.resize.w = size.mX; + event.resize.h = size.mY; + SDL_PushEvent(&event); // copied into queue + + return TRUE; + } + + return FALSE; +} + + void LLWindowSDL::swapBuffers() { if (mWindow) diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 59719e4046..4e2a269ea3 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -64,6 +64,7 @@ public: /*virtual*/ BOOL getSize(LLCoordWindow *size); /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); + /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 228fbefd19..e07fbddb94 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -872,10 +872,30 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size) return FALSE; } + WINDOWPLACEMENT placement; + placement.length = sizeof(WINDOWPLACEMENT); + + if (!GetWindowPlacement(mWindowHandle, &placement)) return FALSE; + + placement.showCmd = SW_RESTORE; + + if (!SetWindowPlacement(mWindowHandle, &placement)) return FALSE; + moveWindow(position, size); return TRUE; } +BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size) +{ + RECT window_rect = {0, 0, size.mX, size.mY }; + DWORD dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + DWORD dw_style = WS_OVERLAPPEDWINDOW; + + AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); + + return setSizeImpl(LLCoordScreen(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top)); +} + // changing fullscreen resolution BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp) { @@ -886,12 +906,12 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO DWORD current_refresh; DWORD dw_ex_style; DWORD dw_style; - RECT window_rect; + RECT window_rect = {0, 0, 0, 0}; S32 width = size.mX; S32 height = size.mY; BOOL auto_show = FALSE; - if (mhRC) + if (mhRC) { auto_show = TRUE; resetDisplayResolution(); @@ -986,7 +1006,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO dw_ex_style = WS_EX_APPWINDOW; dw_style = WS_POPUP; - // Move window borders out not to cover window contents + // Move window borders out not to cover window contents. + // This converts client rect to window rect, i.e. expands it by the window border size. AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); } // If it failed, we don't want to run fullscreen @@ -1014,6 +1035,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO dw_style = WS_OVERLAPPEDWINDOW; } + // don't post quit messages when destroying old windows mPostQuit = FALSE; @@ -1065,6 +1087,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO return FALSE; } + LL_INFOS("Window") << "Device context retrieved." << llendl ; + if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd))) { close(); @@ -1073,6 +1097,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO return FALSE; } + LL_INFOS("Window") << "Pixel format chosen." << llendl ; + // Verify what pixel format we actually received. if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) @@ -1451,7 +1477,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO } else { - llinfos << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << " context." << llendl; + llinfos << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << + (LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << llendl; done = true; if (LLRender::sGLCoreProfile) @@ -1541,24 +1568,16 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) { - LLCoordScreen screen_pos; - mMousePositionModified = TRUE; if (!mWindowHandle) { return FALSE; } - if (!convertCoords(position, &screen_pos)) - { - return FALSE; - } // Inform the application of the new mouse position (needed for per-frame // hover/picking to function). - LLCoordGL gl_pos; - convertCoords(position, &gl_pos); - mCallbacks->handleMouseMove(this, gl_pos, (MASK)0); + mCallbacks->handleMouseMove(this, position.convert(), (MASK)0); // DEV-18951 VWR-8524 Camera moves wildly when alt-clicking. // Because we have preemptively notified the application of the new @@ -1568,24 +1587,23 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) { } - return SetCursorPos(screen_pos.mX, screen_pos.mY); + LLCoordScreen screen_pos(position.convert()); + return ::SetCursorPos(screen_pos.mX, screen_pos.mY); } BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position) { POINT cursor_point; - LLCoordScreen screen_pos; - if (!mWindowHandle || - !GetCursorPos(&cursor_point)) + if (!mWindowHandle + || !GetCursorPos(&cursor_point) + || !position) { return FALSE; } - screen_pos.mX = cursor_point.x; - screen_pos.mY = cursor_point.y; - - return convertCoords(screen_pos, position); + *position = LLCoordScreen(cursor_point.x, cursor_point.y).convert(); + return TRUE; } void LLWindowWin32::hideCursor() @@ -1803,6 +1821,10 @@ static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse"); LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) { + // Ignore clicks not originated in the client area, i.e. mouse-up events not preceded with a WM_LBUTTONDOWN. + // This helps prevent avatar walking after maximizing the window by double-clicking the title bar. + static bool sHandleLeftMouseUp = true; + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA); @@ -2149,10 +2171,20 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE)); return 0; + case WM_NCLBUTTONDOWN: + { + window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_NCLBUTTONDOWN"); + // A click in a non-client area, e.g. title bar or window border. + sHandleLeftMouseUp = false; + } + break; + case WM_LBUTTONDOWN: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN"); LLFastTimer t2(FTM_MOUSEHANDLER); + sHandleLeftMouseUp = true; + if (LLWinImm::isAvailable() && window_imp->mPreeditor) { window_imp->interruptLanguageTextInput(); @@ -2163,15 +2195,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // If we don't do this, many clicks could get buffered up, and if the // first click changes the cursor position, all subsequent clicks // will occur at the wrong location. JC - LLCoordWindow cursor_coord_window; if (window_imp->mMousePositionModified) { + LLCoordWindow cursor_coord_window; window_imp->getCursorPosition(&cursor_coord_window); - window_imp->convertCoords(cursor_coord_window, &gl_coord); + gl_coord = cursor_coord_window.convert(); } else { - window_imp->convertCoords(window_coord, &gl_coord); + gl_coord = window_coord.convert(); } MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates @@ -2193,15 +2225,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // If we don't do this, many clicks could get buffered up, and if the // first click changes the cursor position, all subsequent clicks // will occur at the wrong location. JC - LLCoordWindow cursor_coord_window; if (window_imp->mMousePositionModified) { + LLCoordWindow cursor_coord_window; window_imp->getCursorPosition(&cursor_coord_window); - window_imp->convertCoords(cursor_coord_window, &gl_coord); + gl_coord = cursor_coord_window.convert(); } else { - window_imp->convertCoords(window_coord, &gl_coord); + gl_coord = window_coord.convert(); } MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates @@ -2217,6 +2249,13 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP"); LLFastTimer t2(FTM_MOUSEHANDLER); + + if (!sHandleLeftMouseUp) + { + sHandleLeftMouseUp = true; + break; + } + //if (gDebugClicks) //{ // LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; @@ -2226,15 +2265,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // If we don't do this, many clicks could get buffered up, and if the // first click changes the cursor position, all subsequent clicks // will occur at the wrong location. JC - LLCoordWindow cursor_coord_window; if (window_imp->mMousePositionModified) { + LLCoordWindow cursor_coord_window; window_imp->getCursorPosition(&cursor_coord_window); - window_imp->convertCoords(cursor_coord_window, &gl_coord); + gl_coord = cursor_coord_window.convert(); } else { - window_imp->convertCoords(window_coord, &gl_coord); + gl_coord = window_coord.convert(); } MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates @@ -2261,15 +2300,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // If we don't do this, many clicks could get buffered up, and if the // first click changes the cursor position, all subsequent clicks // will occur at the wrong location. JC - LLCoordWindow cursor_coord_window; if (window_imp->mMousePositionModified) { + LLCoordWindow cursor_coord_window; window_imp->getCursorPosition(&cursor_coord_window); - window_imp->convertCoords(cursor_coord_window, &gl_coord); + gl_coord = cursor_coord_window.convert(); } else { - window_imp->convertCoords(window_coord, &gl_coord); + gl_coord = window_coord.convert(); } MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates @@ -2290,15 +2329,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // If we don't do this, many clicks could get buffered up, and if the // first click changes the cursor position, all subsequent clicks // will occur at the wrong location. JC - LLCoordWindow cursor_coord_window; if (window_imp->mMousePositionModified) { + LLCoordWindow cursor_coord_window; window_imp->getCursorPosition(&cursor_coord_window); - window_imp->convertCoords(cursor_coord_window, &gl_coord); + gl_coord = cursor_coord_window.convert(); } else { - window_imp->convertCoords(window_coord, &gl_coord); + gl_coord = window_coord.convert(); } MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates @@ -2325,15 +2364,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // If we don't do this, many clicks could get buffered up, and if the // first click changes the cursor position, all subsequent clicks // will occur at the wrong location. JC - LLCoordWindow cursor_coord_window; if (window_imp->mMousePositionModified) { + LLCoordWindow cursor_coord_window; window_imp->getCursorPosition(&cursor_coord_window); - window_imp->convertCoords(cursor_coord_window, &gl_coord); + gl_coord = cursor_coord_window.convert(); } else { - window_imp->convertCoords(window_coord, &gl_coord); + gl_coord = window_coord.convert(); } MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates @@ -2354,15 +2393,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // If we don't do this, many clicks could get buffered up, and if the // first click changes the cursor position, all subsequent clicks // will occur at the wrong location. JC - LLCoordWindow cursor_coord_window; if (window_imp->mMousePositionModified) { + LLCoordWindow cursor_coord_window; window_imp->getCursorPosition(&cursor_coord_window); - window_imp->convertCoords(cursor_coord_window, &gl_coord); + gl_coord = cursor_coord_window.convert(); } else { - window_imp->convertCoords(window_coord, &gl_coord); + gl_coord = window_coord.convert(); } MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates @@ -2434,9 +2473,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_MOUSEMOVE: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE"); - window_imp->convertCoords(window_coord, &gl_coord); MASK mask = gKeyboard->currentMask(TRUE); - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask); return 0; } @@ -3324,7 +3362,7 @@ void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position ) LLWinImm::setCompositionWindow( himc, &ime_form ); - sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY ); + sWinIMEWindowPosition = win_pos; } LLWinImm::releaseContext(mWindowHandle, himc); diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index b3602be8b7..54c9ac4d4d 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -58,6 +58,7 @@ public: /*virtual*/ BOOL getSize(LLCoordWindow *size); /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); + /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index bf38a8b062..597031ec70 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -92,6 +92,8 @@ typedef enum e_control_type class LLControlVariable : public LLRefCount { + LOG_CLASS(LLControlVariable); + friend class LLControlGroup; public: @@ -180,6 +182,8 @@ T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& contro //const U32 STRING_CACHE_SIZE = 10000; class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string> { + LOG_CLASS(LLControlGroup); + protected: typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t; ctrl_name_table_t mNameTable; diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 2b4a0fc2a1..2ffb0d8503 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -631,13 +631,14 @@ bool LLXMLNode::updateNode( } //update all of node's children with updateNodes children that match name - LLXMLNodePtr child; + LLXMLNodePtr child = node->getFirstChild(); + LLXMLNodePtr last_child = child; LLXMLNodePtr updateChild; for (updateChild = update_node->getFirstChild(); updateChild.notNull(); updateChild = updateChild->getNextSibling()) { - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) + while(child.notNull()) { std::string nodeName; std::string updateName; @@ -656,6 +657,22 @@ bool LLXMLNode::updateNode( if ((nodeName != "") && (updateName == nodeName)) { updateNode(child, updateChild); + last_child = child; + child = child->getNextSibling(); + if (child.isNull()) + { + child = node->getFirstChild(); + } + break; + } + + child = child->getNextSibling(); + if (child.isNull()) + { + child = node->getFirstChild(); + } + if (child == last_child) + { break; } } @@ -784,7 +801,7 @@ bool LLXMLNode::parseStream( while(str.good()) { str.read((char*)buffer, BUFSIZE); - int count = str.gcount(); + int count = (int)str.gcount(); if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK) { @@ -882,11 +899,8 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root, for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor) { - std::string nodeName; - std::string updateName; - std::string layer_filename = *itor; - if(layer_filename.empty()) + if(layer_filename.empty() || layer_filename == filename) { // no localized version of this file, that's ok, keep looking continue; @@ -898,6 +912,9 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root, return false; } + std::string nodeName; + std::string updateName; + updateRoot->getAttributeString("name", updateName); root->getAttributeString("name", nodeName); diff --git a/indra/llxuixml/CMakeLists.txt b/indra/llxuixml/CMakeLists.txt deleted file mode 100644 index daed4de6ce..0000000000 --- a/indra/llxuixml/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -# -*- cmake -*- - -project(llxuixml) - -include(00-Common) -include(LLCommon) -include(LLMath) -include(LLXML) - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ${LLMATH_INCLUDE_DIRS} - ${LLXML_INCLUDE_DIRS} - ) - -set(llxuixml_SOURCE_FILES - llinitparam.cpp - lltrans.cpp - lluicolor.cpp - llxuiparser.cpp - ) - -set(llxuixml_HEADER_FILES - CMakeLists.txt - - llinitparam.h - lltrans.h - llregistry.h - lluicolor.h - llxuiparser.h - ) - -set_source_files_properties(${llxuixml_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND llxuixml_SOURCE_FILES ${llxuixml_HEADER_FILES}) - -add_library (llxuixml ${llxuixml_SOURCE_FILES}) -# Libraries on which this library depends, needed for Linux builds -# Sort by high-level to low-level -target_link_libraries(llxuixml - llxml - llcommon - llmath - ) diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h index 7dd21bb1ad..a294def734 100644 --- a/indra/lscript/lscript_byteformat.h +++ b/indra/lscript/lscript_byteformat.h @@ -529,6 +529,7 @@ typedef enum e_lscript_runtime_permissions SCRIPT_PERMISSION_CHANGE_PERMISSIONS, SCRIPT_PERMISSION_TRACK_CAMERA, SCRIPT_PERMISSION_CONTROL_CAMERA, + SCRIPT_PERMISSION_TELEPORT, SCRIPT_PERMISSION_EOF } LSCRIPTRunTimePermissions; @@ -545,6 +546,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] = (0x1 << 9), // SCRIPT_PERMISSION_CHANGE_PERMISSIONS (0x1 << 10),// SCRIPT_PERMISSION_TRACK_CAMERA (0x1 << 11),// SCRIPT_PERMISSION_CONTROL_CAMERA + (0x1 << 12),// SCRIPT_PERMISSION_TELEPORT }; // http_request string constants diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index 4e103ae2ba..96b7e57e97 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -212,7 +212,8 @@ extern "C" { int yyerror(const char *fmt, ...); } "PERMISSION_CHANGE_JOINTS" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CHANGE_JOINTS]; return(INTEGER_CONSTANT); } "PERMISSION_CHANGE_PERMISSIONS" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CHANGE_PERMISSIONS]; return(INTEGER_CONSTANT); } "PERMISSION_TRACK_CAMERA" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TRACK_CAMERA]; return(INTEGER_CONSTANT); } -"PERMISSION_CONTROL_CAMERA" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CONTROL_CAMERA]; return(INTEGER_CONSTANT); } +"PERMISSION_CONTROL_CAMERA" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CONTROL_CAMERA]; return(INTEGER_CONSTANT); } +"PERMISSION_TELEPORT" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TELEPORT]; return(INTEGER_CONSTANT); } "INVENTORY_TEXTURE" { count(); yylval.ival = LLAssetType::AT_TEXTURE; return(INTEGER_CONSTANT); } "INVENTORY_SOUND" { count(); yylval.ival = LLAssetType::AT_SOUND; return(INTEGER_CONSTANT); } diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp index 809f66cb1d..aa45c5d23f 100644 --- a/indra/mac_updater/mac_updater.cpp +++ b/indra/mac_updater/mac_updater.cpp @@ -1188,9 +1188,7 @@ void *updatethreadproc(void*) llinfos << "Clearing cache..." << llendl; - char mask[LL_MAX_PATH]; /* Flawfinder: ignore */ - snprintf(mask, LL_MAX_PATH, "%s*.*", gDirUtilp->getDirDelimiter().c_str()); - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask); + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); llinfos << "Clear complete." << llendl; diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 999f754dcf..24328202cb 100644 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -705,7 +705,7 @@ private: // look up "Display Name" in meta data OSType meta_data_key = kQTMetaDataCommonKeyDisplayName; QTMetaDataItem item = kQTMetaDataItemUninitialized; - result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, + result = (OSErr)QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, 0, kQTMetaDataKeyFormatCommon, (const UInt8 *)&meta_data_key, sizeof( meta_data_key ), &item ); @@ -714,14 +714,14 @@ private: // find the size of the title ByteCount size; - result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size ); + result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size ); if ( noErr != result || size <= 0 /*|| size > 1024 FIXME: arbitrary limit */ ) return false; // allocate some space and grab it UInt8* item_data = new UInt8[ size + 1 ]; memset( item_data, 0, ( size + 1 ) * sizeof( UInt8 ) ); - result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL ); + result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL ); if ( noErr != result ) { delete [] item_data; diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 47f8dcd545..1812abd7d5 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -991,7 +991,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) { if(message_name == "set_volume") { - F32 volume = message_in.getValueReal("volume"); + F32 volume = (F32)message_in.getValueReal("volume"); setVolume(volume); } } @@ -1057,9 +1057,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) S32 height = message_in.getValueS32("height"); S32 texture_width = message_in.getValueS32("texture_width"); S32 texture_height = message_in.getValueS32("texture_height"); - mBackgroundR = message_in.getValueReal("background_r"); - mBackgroundG = message_in.getValueReal("background_g"); - mBackgroundB = message_in.getValueReal("background_b"); + mBackgroundR = (F32)message_in.getValueReal("background_r"); + mBackgroundG = (F32)message_in.getValueReal("background_g"); + mBackgroundB = (F32)message_in.getValueReal("background_b"); // mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha if(!name.empty()) @@ -1245,9 +1245,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) if(message_name == "js_agent_location") { #if LLQTWEBKIT_API_VERSION >= 9 - F32 x = message_in.getValueReal("x"); - F32 y = message_in.getValueReal("y"); - F32 z = message_in.getValueReal("z"); + F32 x = (F32)message_in.getValueReal("x"); + F32 y = (F32)message_in.getValueReal("y"); + F32 z = (F32)message_in.getValueReal("z"); LLQtWebKit::getInstance()->setAgentLocation( x, y, z ); LLQtWebKit::getInstance()->emitLocation(); #endif @@ -1256,9 +1256,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) if(message_name == "js_agent_global_location") { #if LLQTWEBKIT_API_VERSION >= 9 - F32 x = message_in.getValueReal("x"); - F32 y = message_in.getValueReal("y"); - F32 z = message_in.getValueReal("z"); + F32 x = (F32)message_in.getValueReal("x"); + F32 y = (F32)message_in.getValueReal("y"); + F32 z = (F32)message_in.getValueReal("z"); LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z ); LLQtWebKit::getInstance()->emitLocation(); #endif @@ -1267,7 +1267,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) if(message_name == "js_agent_orientation") { #if LLQTWEBKIT_API_VERSION >= 9 - F32 angle = message_in.getValueReal("angle"); + F32 angle = (F32)message_in.getValueReal("angle"); LLQtWebKit::getInstance()->setAgentOrientation( angle ); LLQtWebKit::getInstance()->emitLocation(); #endif @@ -1323,7 +1323,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) else if(message_name == "set_page_zoom_factor") { #if LLQTWEBKIT_API_VERSION >= 15 - F32 factor = message_in.getValueReal("factor"); + F32 factor = (F32)message_in.getValueReal("factor"); LLQtWebKit::getInstance()->setPageZoomFactor(factor); #else llwarns << "Ignoring setPageZoomFactor message (llqtwebkit version is too old)." << llendl; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f85b943c70..a925a39246 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -30,7 +30,6 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) -include(LLXUIXML) include(LScript) include(Linking) include(NDOF) @@ -41,12 +40,13 @@ include(UnixInstall) include(LLKDU) include(ViewerMiscLibs) include(LLLogin) +include(VisualLeakDetector) include(GLOD) include(CMakeCopyIfDifferent) include_directories( ${DBUSGLIB_INCLUDE_DIRS} - ${JSONCPP_INCLUDE_DIRS} + ${JSONCPP_INCLUDE_DIR} ${GLOD_INCLUDE_DIR} ${LLAUDIO_INCLUDE_DIRS} ${LLCHARACTER_INCLUDE_DIRS} @@ -65,7 +65,6 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLXUIXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS}/lscript_compile ${LLLOGIN_INCLUDE_DIRS} @@ -166,7 +165,7 @@ set(viewer_SOURCE_FILES llfirstuse.cpp llflexibleobject.cpp llfloaterabout.cpp - llfloateranimpreview.cpp + llfloaterbvhpreview.cpp llfloaterauction.cpp llfloateravatar.cpp llfloateravatarpicker.cpp @@ -211,7 +210,6 @@ set(viewer_SOURCE_FILES llfloatermemleak.cpp llfloatermodelpreview.cpp llfloatermodeluploadbase.cpp - llfloatermodelwizard.cpp llfloaternamedesc.cpp llfloaternotificationsconsole.cpp llfloaterobjectweights.cpp @@ -236,6 +234,7 @@ set(viewer_SOURCE_FILES llfloatertelehub.cpp llfloatertestinspectors.cpp llfloatertestlistview.cpp + llfloatertexturefetchdebugger.cpp llfloatertools.cpp llfloatertopobjects.cpp llfloatertos.cpp @@ -287,7 +286,6 @@ set(viewer_SOURCE_FILES llinspectremoteobject.cpp llinspecttoast.cpp llinventorybridge.cpp - llinventoryclipboard.cpp llinventoryfilter.cpp llinventoryfunctions.cpp llinventoryicon.cpp @@ -303,6 +301,7 @@ set(viewer_SOURCE_FILES lllistbrowser.cpp lllistcontextmenu.cpp lllistview.cpp + lllocalbitmaps.cpp lllocaltextureobject.cpp lllocationhistory.cpp lllocationinputctrl.cpp @@ -489,6 +488,7 @@ set(viewer_SOURCE_FILES lltoastnotifypanel.cpp lltoastpanel.cpp lltoastscripttextbox.cpp + lltoastscriptquestion.cpp lltool.cpp lltoolbarview.cpp lltoolbrush.cpp @@ -722,7 +722,7 @@ set(viewer_HEADER_FILES llfirstuse.h llflexibleobject.h llfloaterabout.h - llfloateranimpreview.h + llfloaterbvhpreview.h llfloaterauction.h llfloateravatar.h llfloateravatarpicker.h @@ -767,7 +767,6 @@ set(viewer_HEADER_FILES llfloatermemleak.h llfloatermodelpreview.h llfloatermodeluploadbase.h - llfloatermodelwizard.h llfloaternamedesc.h llfloaternotificationsconsole.h llfloaterobjectweights.h @@ -792,6 +791,7 @@ set(viewer_HEADER_FILES llfloatertelehub.h llfloatertestinspectors.h llfloatertestlistview.h + llfloatertexturefetchdebugger.h llfloatertools.h llfloatertopobjects.h llfloatertos.h @@ -842,7 +842,6 @@ set(viewer_HEADER_FILES llinspectremoteobject.h llinspecttoast.h llinventorybridge.h - llinventoryclipboard.h llinventoryfilter.h llinventoryfunctions.h llinventoryicon.h @@ -859,6 +858,7 @@ set(viewer_HEADER_FILES lllistbrowser.h lllistcontextmenu.h lllistview.h + lllocalbitmaps.h lllocaltextureobject.h lllocationhistory.h lllocationinputctrl.h @@ -1036,6 +1036,7 @@ set(viewer_HEADER_FILES lltoastnotifypanel.h lltoastpanel.h lltoastscripttextbox.h + lltoastscriptquestion.h lltool.h lltoolbarview.h lltoolbrush.h @@ -1345,7 +1346,9 @@ if (WINDOWS) DXGUID_LIBRARY ) +# see EXP-1765 - theory is opengl32.lib needs to be included before gdi32.lib (windows libs) set(viewer_LIBRARIES + opengl32 ${WINDOWS_LIBRARIES} comdlg32 ${DINPUT_LIBRARY} @@ -1355,7 +1358,6 @@ if (WINDOWS) odbccp32 ole32 oleaut32 - opengl32 shell32 Vfw32 winspool @@ -1744,7 +1746,6 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLVFS_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLXML_LIBRARIES} - ${LLXUIXML_LIBRARIES} ${LSCRIPT_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 15434f2b8f..be79f91919 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -1,45 +1,101 @@ <?xml version="1.0"?> <llsd> <map> - <key>help</key> + <!-- Please insert new keys in alphabetical order. --> + <key>analyzeperformance</key> <map> <key>desc</key> - <string>display this help message</string> + <string>When used in conjunction with logperformance, analyzes result of log against baseline.</string> + <key>map-to</key> + <string>AnalyzePerformance</string> + </map> - <key>short</key> - <string>h</string> + <key>autologin</key> + <map> + <key>desc</key> + <string>log in as last saved user</string> + <key>map-to</key> + <string>AutoLogin</string> </map> - <key>port</key> + <key>channel</key> <map> <key>count</key> <integer>1</integer> - <key>map-to</key> - <string>UserConnectionPort</string> + <!-- Special case. Not mapped to a setting. --> </map> - <key>drop</key> + <key>console</key> <map> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>PacketDropPercentage</string> + <string>ShowConsoleWindow</string> </map> - <key>inbw</key> + <key>cooperative</key> <map> + <key>desc</key> + <string>Yield some idle time to local host.</string> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>InBandwidth</string> + <string>YieldTime</string> </map> - <key>outbw</key> + <key>crashonstartup</key> + <map> + <key>desc</key> + <string>Crashes on startup. For QA use.</string> + <key>map-to</key> + <string>CrashOnStartup</string> + </map> + + <key>debugsession</key> + <map> + <key>desc</key> + <string>Run as if RenderDebugGL is TRUE, but log errors until end of session.</string> + <key>map-to</key> + <string>DebugSession</string> + </map> + + <key>debugviews</key> + <map> + <key>map-to</key> + <string>DebugViews</string> + </map> + + <key>disablecrashlogger</key> + <map> + <key>desc</key> + <string>Disables the crash logger and lets the OS handle crashes</string> + <key>map-to</key> + <string>DisableCrashLogger</string> + </map> + + <key>drop</key> <map> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>OutBandwidth</string> + <string>PacketDropPercentage</string> + </map> + + <key>god</key> + <map> + <key>desc</key> + <string>Log in a god if you have god access.</string> + <key>map-to</key> + <string>ConnectAsGod</string> + </map> + + <key>graphicslevel</key> + <map> + <key>desc</key> + <string>Set the detail level. +0 - low, 1 - medium, 2 - high, 3 - ultra</string> + <key>count</key> + <integer>1</integer> </map> <key>grid</key> @@ -52,16 +108,13 @@ <string>CmdLineGridChoice</string> </map> - <key>loginuri</key> + <key>help</key> <map> <key>desc</key> - <string>login server and CGI script to use</string> - <key>count</key> - <integer>1</integer> - <key>compose</key> - <boolean>true</boolean> - <key>map-to</key> - <string>CmdLineLoginURI</string> + <string>display this help message</string> + + <key>short</key> + <string>h</string> </map> <key>helperuri</key> @@ -74,44 +127,73 @@ <string>CmdLineHelperURI</string> </map> - <key>debugviews</key> + <key>ignorepixeldepth</key> <map> + <key>desc</key> + <string>Ignore pixel depth settings.</string> <key>map-to</key> - <string>DebugViews</string> + <string>IgnorePixelDepth</string> </map> - <key>skin</key> + <key>inbw</key> + <map> + <key>count</key> + <integer>1</integer> + <key>map-to</key> + <string>InBandwidth</string> + </map> + + <key>leap</key> <map> <key>desc</key> - <string>ui/branding skin folder to use</string> + <string>command line to run an LLSD Event API Plugin</string> <key>count</key> <integer>1</integer> + <!-- you can specify multiple such plugins --> + <key>compose</key> + <boolean>true</boolean> <key>map-to</key> - <string>SkinFolder</string> + <string>LeapCommand</string> </map> - <key>autologin</key> + <key>logfile</key> + <map> + <key>count</key> + <integer>1</integer> + <key>map-to</key> + <string>UserLogFile</string> + </map> + + <key>login</key> <map> <key>desc</key> - <string>log in as last saved user</string> + <string>3 tokens: first, last and password</string> + <key>count</key> + <integer>3</integer> <key>map-to</key> - <string>AutoLogin</string> + <string>UserLoginInfo</string> </map> - <key>quitafter</key> + <key>loginpage</key> <map> + <key>desc</key> + <string>Login authentication page to use.</string> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>QuitAfterSeconds</string> + <string>LoginPage</string> </map> - <key>logperformance</key> + <key>loginuri</key> <map> <key>desc</key> - <string>Log performance metrics for benchmarking</string> + <string>login server and CGI script to use</string> + <key>count</key> + <integer>1</integer> + <key>compose</key> + <boolean>true</boolean> <key>map-to</key> - <string>LogPerformance</string> + <string>CmdLineLoginURI</string> </map> <key>logmetrics</key> @@ -123,29 +205,35 @@ <key>map-to</key> <string>LogMetrics</string> </map> - - <key>analyzeperformance</key> + + <key>logperformance</key> <map> <key>desc</key> - <string>When used in conjunction with logperformance, analyzes result of log against baseline.</string> + <string>Log performance metrics for benchmarking</string> <key>map-to</key> - <string>AnalyzePerformance</string> + <string>LogPerformance</string> </map> - <key>debugsession</key> + <key>multiple</key> <map> <key>desc</key> - <string>Run as if RenderDebugGL is TRUE, but log errors until end of session.</string> + <string>Allow multiple viewers.</string> <key>map-to</key> - <string>DebugSession</string> + <string>AllowMultipleViewers</string> </map> - <key>replaysession</key> + <key>noaudio</key> + <map> + <key>map-to</key> + <string>NoAudio</string> + </map> + + <key>noinvlib</key> <map> <key>desc</key> - <string>After login, replay last recorded session and quit.</string> + <string>Do not request the inventory library.</string> <key>map-to</key> - <string>ReplaySession</string> + <string>NoInventoryLibrary</string> </map> <key>nonotifications</key> @@ -156,22 +244,10 @@ <string>IgnoreAllNotifications</string> </map> - <key>rotate</key> - <map> - <key>map-to</key> - <string>RotateRight</string> - </map> - - <key>noaudio</key> - <map> - <key>map-to</key> - <string>NoAudio</string> - </map> - - <key>nosound</key> + <key>nopreload</key> <map> <key>map-to</key> - <string>NoAudio</string> + <string>NoPreload</string> </map> <key>noprobe</key> @@ -186,151 +262,134 @@ <string>NoQuickTime</string> </map> - <key>nopreload</key> + <key>nosound</key> <map> <key>map-to</key> - <string>NoPreload</string> + <string>NoAudio</string> </map> - <key>purge</key> + <key>no-verify-ssl-cert</key> <map> - <key>desc</key> - <string>Delete files in the cache.</string> <key>map-to</key> - <string>PurgeCacheOnNextStartup</string> + <string>NoVerifySSLCert</string> </map> - <key>noinvlib</key> + <key>novoice</key> <map> <key>desc</key> - <string>Do not request the inventory library.</string> + <string>Disable voice.</string> <key>map-to</key> - <string>NoInventoryLibrary</string> + <string>CmdLineDisableVoice</string> </map> - <key>logfile</key> + <key>outbw</key> <map> <key>count</key> <integer>1</integer> <key>map-to</key> - <string>UserLogFile</string> + <string>OutBandwidth</string> </map> - <key>graphicslevel</key> + <key>port</key> <map> - <key>desc</key> - <string>Set the detail level. -0 - low, 1 - medium, 2 - high, 3 - ultra</string> <key>count</key> <integer>1</integer> + <key>map-to</key> + <string>UserConnectionPort</string> </map> - <key>setdefault</key> + <key>purge</key> <map> <key>desc</key> - <string>specify the value of a particular configuration variable which can be overridden by settings.xml.</string> - <key>count</key> - <integer>2</integer> - <!-- Special case. Mapped to settings procedurally. --> + <string>Delete files in the cache.</string> + <key>map-to</key> + <string>PurgeCacheOnNextStartup</string> </map> - <key>set</key> + <key>qa</key> <map> <key>desc</key> - <string>specify the value of a particular configuration variable that overrides all other settings.</string> - <key>count</key> - <integer>2</integer> - <key>compose</key> - <boolean>true</boolean> - <!-- Special case. Mapped to settings procedurally. --> + <string>Activated debugging menu in Advanced Settings.</string> + <key>map-to</key> + <string>QAMode</string> </map> - <key>settings</key> + <key>quitafter</key> <map> - <key>desc</key> - <string>Specify the filename of a configuration file.</string> <key>count</key> <integer>1</integer> - <!-- Special case. Mapped to settings procedurally. --> + <key>map-to</key> + <string>QuitAfterSeconds</string> </map> - - <key>sessionsettings</key> + + <key>replaysession</key> <map> <key>desc</key> - <string>Specify the filename of a configuration file that contains temporary per-session configuration overrides.</string> - <key>count</key> - <integer>1</integer> - <!-- Special case. Mapped to settings procedurally. --> + <string>After login, replay last recorded session and quit.</string> + <key>map-to</key> + <string>ReplaySession</string> </map> - <key>usersessionsettings</key> - <map> - <key>desc</key> - <string>Specify the filename of a configuration file that contains temporary per-session configuration user overrides.</string> - <key>count</key> - <integer>1</integer> - <!-- Special case. Mapped to settings procedurally. --> - </map> - - <key>login</key> + <key>rotate</key> <map> - <key>desc</key> - <string>3 tokens: first, last and password</string> - <key>count</key> - <integer>3</integer> <key>map-to</key> - <string>UserLoginInfo</string> + <string>RotateRight</string> </map> - <key>god</key> + <key>safe</key> <map> <key>desc</key> - <string>Log in a god if you have god access.</string> + <string>Reset preferences, run in safe mode.</string> <key>map-to</key> - <string>ConnectAsGod</string> + <string>SafeMode</string> </map> - <key>console</key> + <key>sessionsettings</key> <map> + <key>desc</key> + <string>Specify the filename of a configuration file that contains temporary per-session configuration overrides.</string> <key>count</key> <integer>1</integer> - <key>map-to</key> - <string>ShowConsoleWindow</string> + <!-- Special case. Mapped to settings procedurally. --> </map> - <key>safe</key> + <key>set</key> <map> <key>desc</key> - <string>Reset preferences, run in safe mode.</string> - <key>map-to</key> - <string>SafeMode</string> + <string>specify the value of a particular configuration variable that overrides all other settings.</string> + <key>count</key> + <integer>2</integer> + <key>compose</key> + <boolean>true</boolean> + <!-- Special case. Mapped to settings procedurally. --> </map> - <key>multiple</key> + <key>setdefault</key> <map> <key>desc</key> - <string>Allow multiple viewers.</string> - <key>map-to</key> - <string>AllowMultipleViewers</string> + <string>specify the value of a particular configuration variable which can be overridden by settings.xml.</string> + <key>count</key> + <integer>2</integer> + <!-- Special case. Mapped to settings procedurally. --> </map> - <key>novoice</key> + <key>settings</key> <map> <key>desc</key> - <string>Disable voice.</string> - <key>map-to</key> - <string>CmdLineDisableVoice</string> + <string>Specify the filename of a configuration file.</string> + <key>count</key> + <integer>1</integer> + <!-- Special case. Mapped to settings procedurally. --> </map> - <key>url</key> + <key>skin</key> <map> <key>desc</key> - <string>Startup location</string> + <string>ui/branding skin folder to use</string> <key>count</key> <integer>1</integer> - <key>last_option</key> - <boolean>true</boolean> - <!-- Special case. Not mapped to a setting. --> + <key>map-to</key> + <string>SkinFolder</string> </map> <key>slurl</key> @@ -346,69 +405,24 @@ <!-- Special case. Not mapped to a setting. --> </map> - <key>ignorepixeldepth</key> - <map> - <key>desc</key> - <string>Ignore pixel depth settings.</string> - <key>map-to</key> - <string>IgnorePixelDepth</string> - </map> - - <key>cooperative</key> + <key>url</key> <map> <key>desc</key> - <string>Yield some idle time to local host.</string> - <key>count</key> - <integer>1</integer> - <key>map-to</key> - <string>YieldTime</string> - </map> - - <key>no-verify-ssl-cert</key> - <map> - <key>map-to</key> - <string>NoVerifySSLCert</string> - </map> - - <key>channel</key> - <map> + <string>Startup location</string> <key>count</key> <integer>1</integer> + <key>last_option</key> + <boolean>true</boolean> <!-- Special case. Not mapped to a setting. --> </map> - <key>loginpage</key> + <key>usersessionsettings</key> <map> <key>desc</key> - <string>Login authentication page to use.</string> + <string>Specify the filename of a configuration file that contains temporary per-session configuration user overrides.</string> <key>count</key> <integer>1</integer> - <key>map-to</key> - <string>LoginPage</string> - </map> - - <key>qa</key> - <map> - <key>desc</key> - <string>Activated debugging menu in Advanced Settings.</string> - <key>map-to</key> - <string>QAMode</string> - </map> - - <key>crashonstartup</key> - <map> - <key>desc</key> - <string>Crashes on startup. For QA use.</string> - <key>map-to</key> - <string>CrashOnStartup</string> - </map> - - <key>disablecrashlogger</key> - <map> - <key>desc</key> - <string>Disables the crash logger and lets the OS handle crashes</string> - <key>map-to</key> - <string>DisableCrashLogger</string> + <!-- Special case. Mapped to settings procedurally. --> </map> </map> </llsd> diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 1d1d39c786..73df064ab2 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -37,6 +37,8 @@ tooltip_ref="Command_Build_Tooltip" execute_function="Build.Toggle" execute_parameters="build" + is_enabled_function="Build.Enabled" + is_enabled_parameters="build" is_running_function="Floater.IsOpen" is_running_parameters="build" /> diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index 82b43432eb..318b69438a 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -91,6 +91,7 @@ PERMISSION_CHANGE_LINKS Passed to llRequestPermissions library function to req # PERMISSION_CHANGE_PERMISSIONS Passed to llRequestPermissions library function to request permission to change permissions PERMISSION_TRACK_CAMERA Passed to llRequestPermissions library function to request permission to track agent's camera PERMISSION_CONTROL_CAMERA Passed to llRequestPermissions library function to request permission to change agent's camera +PERMISSION_TELEPORT Passed to llRequestPermissions library function to request permission to teleport agent DEBUG_CHANNEL Chat channel reserved for debug and error messages from scripts PUBLIC_CHANNEL Chat channel that broadcasts to all nearby users diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index a76eb3cd37..64122bbb6c 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -20,7 +20,7 @@ <key>tags</key> <array> <string>AppInit</string> - <string>Capabilities</string> + <string>Capabilities</string> <string>SystemInfo</string> <string>TextureCache</string> <string>AppCache</string> @@ -42,8 +42,10 @@ </array> <key>tags</key> <array> - <!-- sample entry for debugging a specific item --> -<!-- <string>Voice</string> --> + <!-- sample entry for debugging specific items + <string>Avatar</string> + <string>Voice</string> + --> </array> </map> </array> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0e26013152..c9b4de0140 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -335,17 +335,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>AuditTexture</key> - <map> - <key>Comment</key> - <string>Enable texture auditting.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>AutoAcceptNewInventory</key> <map> <key>Comment</key> @@ -621,6 +610,28 @@ <key>Value</key> <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/avatars.html</string> </map> + <key>AvatarRotateThresholdSlow</key> + <map> + <key>Comment</key> + <string>Angle between avatar facing and camera facing at which avatar turns to face same direction as camera, when moving slowly (degrees)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>60</integer> + </map> + <key>AvatarRotateThresholdFast</key> + <map> + <key>Comment</key> + <string>Angle between avatar facing and camera facing at which avatar turns to face same direction as camera, when moving fast (degrees)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>2</integer> + </map> <key>AvatarBakedTextureUploadTimeout</key> <map> <key>Comment</key> @@ -1914,7 +1925,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>DebugBeaconLineWidth</key> <map> @@ -4579,6 +4590,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>LeapCommand</key> + <map> + <key>Comment</key> + <string>Zero or more command lines to run LLSD Event API Plugin programs.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <array /> + </map> <key>LSLFindCaseInsensitivity</key> <map> <key>Comment</key> @@ -7142,7 +7164,7 @@ <key>QAModeEventHostPort</key> <map> <key>Comment</key> - <string>Port on which lleventhost should listen</string> + <string>DEPRECATED: Port on which lleventhost should listen</string> <key>Persist</key> <integer>0</integer> <key>Type</key> @@ -7161,6 +7183,17 @@ <key>Value</key> <integer>-1</integer> </map> + <key>QAModeMetrics</key> + <map> + <key>Comment</key> + <string>"Enables QA features (logging, faster cycling) for metrics collector"</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>QuietSnapshotsToDisk</key> <map> <key>Comment</key> @@ -7609,6 +7642,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderCompressTextures</key> + <map> + <key>Comment</key> + <string>Enable texture compression on OpenGL 3.0 and later implementations (EXPERIMENTAL, requires restart)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderPerformanceTest</key> <map> <key>Comment</key> @@ -8217,7 +8261,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <real>128</real> + <real>512</real> </map> <key>RenderSpecularResY</key> @@ -8241,7 +8285,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>8</real> + <real>384</real> </map> <key>RenderDeferred</key> @@ -9101,28 +9145,19 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderUseShaderLOD</key> - <map> - <key>Comment</key> - <string>Whether we want to have different shaders for LOD</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>RenderUseShaderNearParticles</key> - <map> - <key>Comment</key> - <string>Whether we want to use shaders on near particles</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> + + <key>RenderAutoHideSurfaceAreaLimit</key> + <map> + <key>Comment</key> + <string>Maximum surface area of a set of proximal objects inworld before automatically hiding geometry to prevent system overload.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderVBOEnable</key> <map> <key>Comment</key> @@ -9608,18 +9643,29 @@ <key>Value</key> <integer>1</integer> </map> - <key>ShowConsoleWindow</key> - <map> - <key>Comment</key> - <string>Show log in separate OS window</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>NavBarShowCoordinates</key> + <key>ShowConsoleWindow</key> + <map> + <key>Comment</key> + <string>Show log in separate OS window</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>EnableVisualLeakDetector</key> + <map> + <key>Comment</key> + <string>EnableVisualLeakDetector</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>NavBarShowCoordinates</key> <map> <key>Comment</key> <string>Show coordinates in navigation bar</string> @@ -10631,6 +10677,39 @@ <key>Value</key> <real>20.0</real> </map> + <key>TexelPixelRatio</key> + <map> + <key>Comment</key> + <string>texel pixel ratio = texel / pixel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> + <key>TextureCameraMotionThreshold</key> + <map> + <key>Comment</key> + <string>If the overall motion is lower than this value, textures will be loaded faster</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.2</real> + </map> + <key>TextureCameraMotionBoost</key> + <map> + <key>Comment</key> + <string>Progressive discard level decrement when the camera is still</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>3</integer> + </map> <key>TextureDecodeDisabled</key> <map> <key>Comment</key> @@ -10664,6 +10743,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>TextureFetchDebuggerEnabled</key> + <map> + <key>Comment</key> + <string>Enable the texture fetching debugger if set</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>TextureLoadFullRes</key> <map> <key>Comment</key> @@ -10686,6 +10776,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>TextureNewByteRange</key> + <map> + <key>Comment</key> + <string>Use the new more accurate byte range computation for j2c discard levels</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>TexturePickerShowFolders</key> <map> <key>Comment</key> @@ -10708,6 +10809,17 @@ <key>Value</key> <integer>2</integer> </map> + <key>TextureReverseByteRange</key> + <map> + <key>Comment</key> + <string>Minimal percent of the optimal byte range allowed to render a given discard level</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>50</integer> + </map> <key>ThrottleBandwidthKBPS</key> <map> <key>Comment</key> @@ -12755,7 +12867,7 @@ <key>WindowX</key> <map> <key>Comment</key> - <string>X coordinate of lower left corner of SL viewer window, relative to primary display (pixels)</string> + <string>X coordinate of upper left corner of SL viewer window, relative to upper left corner of primary display (pixels)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -12766,7 +12878,7 @@ <key>WindowY</key> <map> <key>Comment</key> - <string>Y coordinate of lower left corner of SL viewer window, relative to primary display (pixels)</string> + <string>Y coordinate of upper left corner of SL viewer window, relative to upper left corner of primary display (pixels)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 8cdd8ed838..143126b334 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -33,6 +33,28 @@ <key>Value</key> <string /> </map> + <key>InventoryInboxHeight</key> + <map> + <key>Comment</key> + <string>Inventory inbox panel height in Inventory floater.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>200</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>DisplayDestinationsOnInitialRun</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl index 3e4d438ed3..7a35905280 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -34,5 +36,5 @@ uniform sampler2D diffuseMap; void main() { - gl_FragColor = vec4(vertex_color.rgb, texture2D(diffuseMap, vary_texcoord0.xy).a); + frag_color = vec4(vertex_color.rgb, texture2D(diffuseMap, vary_texcoord0.xy).a); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index c012efa056..dd87ddb330 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -26,15 +26,15 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect depthMap; vec4 diffuseLookup(vec2 texcoord); -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; uniform vec2 screen_res; vec3 atmosLighting(vec3 light); @@ -69,6 +69,6 @@ void main() color.rgb += diff.rgb * vary_pointlight_col.rgb; - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl index 8641827777..beb3290187 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl @@ -26,15 +26,15 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect depthMap; uniform sampler2D diffuseMap; -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; uniform vec2 screen_res; vec3 atmosLighting(vec3 light); @@ -81,9 +81,9 @@ void main() color.rgb += diff.rgb * vary_pointlight_col.rgb; - gl_FragColor = color; - //gl_FragColor = vec4(1,0,1,1); - //gl_FragColor = vec4(1,0,1,1)*shadow; + frag_color = color; + //frag_color = vec4(1,0,1,1); + //frag_color = vec4(1,0,1,1)*shadow; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl index c13ea702db..cb87b754b4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl @@ -26,14 +26,14 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect depthMap; uniform sampler2D diffuseMap; -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; uniform vec2 screen_res; vec3 atmosLighting(vec3 light); @@ -79,6 +79,6 @@ void main() color.rgb += diff.rgb * vary_pointlight_col.rgb; - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl index 40b0cf47ac..5a0e8ff684 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl @@ -41,7 +41,6 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); VARYING vec3 vary_position; VARYING vec3 vary_ambient; VARYING vec3 vary_directional; -VARYING vec3 vary_normal; VARYING vec3 vary_fragcoord; VARYING vec3 vary_pointlight_col; VARYING vec4 vertex_color; @@ -55,6 +54,12 @@ uniform vec3 light_direction[8]; uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) { //get light vector @@ -104,8 +109,7 @@ void main() gl_Position = frag_pos; vary_position = pos.xyz; - vary_normal = norm; - + calcAtmospherics(pos.xyz); vec4 col = vec4(0.0, 0.0, 0.0, diffuse_color.a); diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 8c96d55342..cf38a2f4f7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -48,7 +48,6 @@ VARYING vec3 vary_ambient; VARYING vec3 vary_directional; VARYING vec3 vary_fragcoord; VARYING vec3 vary_position; -VARYING vec3 vary_light; VARYING vec3 vary_pointlight_col; VARYING vec4 vertex_color; @@ -64,6 +63,12 @@ uniform vec3 light_direction[8]; uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) { //get light vector @@ -128,8 +133,6 @@ void main() // Add windlight lights col.rgb = atmosAmbient(vec3(0.)); - vary_light = light_position[0].xyz; - vary_ambient = col.rgb*diffuse_color.rgb; vary_directional.rgb = diffuse_color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), (1.0-diffuse_color.a)*(1.0-diffuse_color.a))); diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl index 402f681631..22c9a4d14e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl @@ -23,17 +23,17 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D diffuseMap; -VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; void main() { - //gl_FragColor = vec4(1,1,1,vertex_color.a * texture2D(diffuseMap, vary_texcoord0.xy).a); - gl_FragColor = vec4(1,1,1,1); + frag_color = vec4(1,1,1,1); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl index ded6cced27..81961d7746 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl @@ -27,11 +27,8 @@ uniform mat4 modelview_matrix; uniform mat4 texture_matrix0; ATTRIBUTE vec3 position; -ATTRIBUTE vec4 diffuse_color; ATTRIBUTE vec2 texcoord0; -VARYING vec4 vertex_color; - mat4 getObjectSkinnedTransform(); void main() @@ -42,8 +39,6 @@ void main() mat = modelview_matrix * mat; vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - vertex_color = diffuse_color; - vec4 p = projection_matrix * vec4(pos, 1.0); p.z = max(p.z, -p.w+0.01); gl_Position = p; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl new file mode 100644 index 0000000000..5f395801e5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl @@ -0,0 +1,148 @@ +/** + * @file avatarAlphaNoColorV.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 projection_matrix; + +ATTRIBUTE vec3 position; +ATTRIBUTE vec3 normal; +ATTRIBUTE vec2 texcoord0; + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +mat4 getSkinnedTransform(); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +VARYING vec3 vary_position; +VARYING vec3 vary_ambient; +VARYING vec3 vary_directional; +VARYING vec3 vary_fragcoord; +VARYING vec3 vary_pointlight_col; +VARYING vec2 vary_texcoord0; + + +uniform float near_clip; + +uniform vec4 color; + +uniform vec4 light_position[8]; +uniform vec3 light_direction[8]; +uniform vec3 light_attenuation[8]; +uniform vec3 light_diffuse[8]; + +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = dot(lv,lv); + + float da = 0.0; + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv = normalize(lv); + + //distance attenuation + float dist2 = d/la; + da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= max(dot(n, lv), 0.0); + } + + return da; +} + +void main() +{ + vary_texcoord0 = texcoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + vec4 pos_in = vec4(position.xyz, 1.0); + pos.x = dot(trans[0], pos_in); + pos.y = dot(trans[1], pos_in); + pos.z = dot(trans[2], pos_in); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, normal); + norm.y = dot(trans[1].xyz, normal); + norm.z = dot(trans[2].xyz, normal); + norm = normalize(norm); + + vec4 frag_pos = projection_matrix * pos; + gl_Position = frag_pos; + + vary_position = pos.xyz; + + calcAtmospherics(pos.xyz); + + vec4 col = vec4(0.0, 0.0, 0.0, 1.0); + + // Collect normal lights + col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z); + col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z); + col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z); + col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z); + col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z); + col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z); + + vary_pointlight_col = col.rgb*color.rgb; + + col.rgb = vec3(0,0,0); + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + + vary_ambient = col.rgb*color.rgb; + vary_directional = color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), 0.0)); + + col.rgb = col.rgb * color.rgb; + + vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip); +} + + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index c0edddc40a..d6149fcc32 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -59,6 +59,12 @@ uniform vec3 light_direction[8]; uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) { //get light vector diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 9a3b2e3e8a..46d2aa4877 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif uniform sampler2D diffuseMap; @@ -41,9 +43,9 @@ void main() discard; } - gl_FragData[0] = vec4(diff.rgb, 0.0); - gl_FragData[1] = vec4(0,0,0,0); + frag_data[0] = vec4(diff.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index 558a88009a..3686f2f647 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D diffuseMap; @@ -33,7 +35,7 @@ VARYING vec4 post_pos; void main() { - gl_FragColor = vec4(1,1,1,1); + frag_color = vec4(1,1,1,1); gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 60d4dae99f..f400eb7a5b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect depthMap; @@ -111,6 +113,6 @@ void main() col /= defined_weight.xyxx; col.y *= col.y; - gl_FragColor = col; + frag_color = col; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 6cc5f23aca..680eadb852 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif uniform sampler2D diffuseMap; @@ -46,9 +48,9 @@ void main() dot(norm,vary_mat1), dot(norm,vary_mat2)); - gl_FragData[0] = vec4(col, 0.0); - gl_FragData[1] = vertex_color.aaaa; // spec - //gl_FragData[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested + frag_data[0] = vec4(col, 0.0); + frag_data[1] = vertex_color.aaaa; // spec + //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(tnorm); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl index 6c205074b4..8ba75010a2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl @@ -30,7 +30,7 @@ ATTRIBUTE vec3 position; ATTRIBUTE vec4 diffuse_color; ATTRIBUTE vec3 normal; ATTRIBUTE vec2 texcoord0; -ATTRIBUTE vec2 texcoord2; +ATTRIBUTE vec3 binormal; VARYING vec3 vary_mat0; VARYING vec3 vary_mat1; @@ -52,7 +52,7 @@ void main() vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz); - vec3 b = normalize((mat * vec4(vec4(texcoord2,0,1).xyz+position.xyz, 1.0)).xyz-pos.xyz); + vec3 b = normalize((mat * vec4(binormal.xyz+position.xyz, 1.0)).xyz-pos.xyz); vec3 t = cross(b, n); vary_mat0 = vec3(t.x, b.x, n.x); diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl index db272cf601..1d8ca04ccd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl @@ -25,7 +25,9 @@ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif ///////////////////////////////////////////////////////////////////////// @@ -98,8 +100,8 @@ void main() color *= 2.; /// Gamma correct for WL (soft clip effect). - gl_FragData[0] = vec4(scaleSoftClip(color.rgb), alpha1); - gl_FragData[1] = vec4(0.0,0.0,0.0,0.0); - gl_FragData[2] = vec4(0,0,1,0); + frag_data[0] = vec4(scaleSoftClip(color.rgb), alpha1); + frag_data[1] = vec4(0.0,0.0,0.0,0.0); + frag_data[2] = vec4(0,0,1,0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl index 64e094e3c5..17f425475c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl @@ -50,18 +50,18 @@ uniform vec4 sunlight_color; uniform vec4 ambient; uniform vec4 blue_horizon; uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; +uniform float haze_horizon; +uniform float haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 max_y; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y; uniform vec4 glow; uniform vec4 cloud_color; -uniform vec4 cloud_scale; +uniform float cloud_scale; void main() { @@ -77,7 +77,7 @@ void main() // Set altitude if (P.y > 0.) { - P *= (max_y.x / P.y); + P *= (max_y / P.y); } else { @@ -99,12 +99,12 @@ void main() // Sunlight attenuation effect (hue and brightness) due to atmosphere // this is used later for sunlight modulation at various altitudes - light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); // Calculate relative weights - temp1 = blue_density + haze_density.x; + temp1 = blue_density + haze_density; blue_weight = blue_density / temp1; - haze_weight = haze_density.x / temp1; + haze_weight = haze_density / temp1; // Compute sunlight from P & lightnorm (for long rays like sky) temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); @@ -112,7 +112,7 @@ void main() sunlight *= exp( - light_atten * temp2.y); // Distance - temp2.z = Plen * density_multiplier.x; + temp2.z = Plen * density_multiplier; // Transparency (-> temp1) // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati @@ -136,14 +136,14 @@ void main() // Increase ambient when there are more clouds vec4 tmpAmbient = ambient; - tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5; + tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; // Dim sunlight by cloud shadow percentage - sunlight *= (1. - cloud_shadow.x); + sunlight *= (1. - cloud_shadow); // Haze color below cloud vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient) - + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient) ); // CLOUDS @@ -164,13 +164,13 @@ void main() vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1); // Make a nice cloud density based on the cloud_shadow value that was passed in. - vary_CloudDensity = 2. * (cloud_shadow.x - 0.25); + vary_CloudDensity = 2. * (cloud_shadow - 0.25); // Texture coords vary_texcoord0 = texcoord0; vary_texcoord0.xy -= 0.5; - vary_texcoord0.xy /= cloud_scale.x; + vary_texcoord0.xy /= cloud_scale; vary_texcoord0.xy += 0.5; vary_texcoord1 = vary_texcoord0; diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl index e612efba61..ccbc3c557c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -83,6 +85,6 @@ void main() sc = max(sc, -max_cof); vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res); - gl_FragColor.rgb = diff.rgb + bloom.rgb; - gl_FragColor.a = sc/max_cof*0.5+0.5; + frag_color.rgb = diff.rgb + bloom.rgb; + frag_color.a = sc/max_cof*0.5+0.5; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index e9989a4e48..b2027d3a5d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif uniform float minimum_alpha; @@ -44,9 +46,9 @@ void main() discard; } - gl_FragData[0] = vec4(col.rgb, 0.0); - gl_FragData[1] = vec4(0,0,0,0); // spec + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index fdf8d72b38..ead384b07c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif VARYING vec3 vary_normal; @@ -43,8 +45,8 @@ void main() discard; } - gl_FragData[0] = vec4(col.rgb, 0.0); - gl_FragData[1] = vec4(0,0,0,0); + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl index bb20e2ca47..f73fa6f231 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl @@ -25,7 +25,9 @@ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif uniform float minimum_alpha; @@ -44,9 +46,9 @@ void main() discard; } - gl_FragData[0] = vec4(col.rgb, 0.0); - gl_FragData[1] = vec4(0,0,0,0); // spec + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 7bde49eb86..227aa2aae3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif uniform sampler2D diffuseMap; @@ -36,10 +38,10 @@ VARYING vec2 vary_texcoord0; void main() { vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb; - gl_FragData[0] = vec4(col, 0.0); - gl_FragData[1] = vertex_color.aaaa; // spec - //gl_FragData[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested + frag_data[0] = vec4(col, 0.0); + frag_data[1] = vertex_color.aaaa; // spec + //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(vary_normal); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index 75b45111e0..d442e5403a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif VARYING vec3 vary_normal; @@ -35,9 +37,9 @@ void main() { vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; - gl_FragData[0] = vec4(col, 0.0); - gl_FragData[1] = vertex_color.aaaa; // spec - //gl_FragData[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested + frag_data[0] = vec4(col, 0.0); + frag_data[1] = vertex_color.aaaa; // spec + //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(vary_normal); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl index 01e3505359..a425e5062e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -37,14 +39,24 @@ uniform vec2 screen_res; uniform float max_cof; uniform float res_scale; +uniform float dof_width; +uniform float dof_height; VARYING vec2 vary_fragcoord; +vec4 dofSample(sampler2DRect tex, vec2 tc) +{ + tc.x = min(tc.x, dof_width); + tc.y = min(tc.y, dof_height); + + return texture2DRect(tex, tc); +} + void main() { vec2 tc = vary_fragcoord.xy; - vec4 dof = texture2DRect(diffuseRect, vary_fragcoord.xy*res_scale); + vec4 dof = dofSample(diffuseRect, vary_fragcoord.xy*res_scale); vec4 diff = texture2DRect(lightMap, vary_fragcoord.xy); @@ -63,5 +75,5 @@ void main() diff = mix(diff, col*0.25, a); } - gl_FragColor = mix(diff, dof, a); + frag_color = mix(diff, dof, a); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl index 92f78125d8..6aa4d7b4ed 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif vec3 fullbrightAtmosTransport(vec3 light); @@ -45,6 +47,6 @@ void main() color.rgb = fullbrightScaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index 84ae2f9f10..36433a5827 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -46,6 +48,6 @@ void main() color.rgb = fullbrightScaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl index 5af9406452..e02a7b405b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif #define FXAA_PC 1 @@ -341,18 +343,23 @@ A. Or use FXAA_GREEN_AS_LUMA. // 1 = API supports gather4 on alpha channel. // 0 = API does not support gather4 on alpha channel. // + #if (FXAA_GLSL_130 == 0) + #define FXAA_GATHER4_ALPHA 0 + #endif #if (FXAA_HLSL_5 == 1) #define FXAA_GATHER4_ALPHA 1 #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif #ifndef FXAA_GATHER4_ALPHA - #define FXAA_GATHER4_ALPHA 0 - #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif + #endif #endif /*============================================================================ @@ -2113,6 +2120,6 @@ void main() //diff = texture2D(diffuseMap, vary_tc); - gl_FragColor = diff; + frag_color = diff; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl index 29ca80ae92..da1b234240 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect depthMap; @@ -184,5 +186,5 @@ void main() vec3 norm = texture2DRect(normalMap, pos_screen).xyz; norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm - gl_FragColor.xyz = giAmbient(pos, norm); + frag_color.xyz = giAmbient(pos, norm); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index a44173a2a4..bc0719cb82 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif uniform float minimum_alpha; @@ -45,7 +47,7 @@ void main() discard; } - gl_FragData[0] = vec4(col.rgb, col.a * 0.005); - gl_FragData[1] = texture2D(specularMap, vary_texcoord0.xy); - gl_FragData[2] = vec4(texture2D(normalMap, vary_texcoord0.xy).xyz, 0.0); + frag_data[0] = vec4(col.rgb, col.a * 0.005); + frag_data[1] = texture2D(specularMap, vary_texcoord0.xy); + frag_data[2] = vec4(texture2D(normalMap, vary_texcoord0.xy).xyz, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl index e014a14ad8..dcf474824d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl @@ -26,12 +26,14 @@ uniform sampler2DRect diffuseMap; #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec2 vary_fragcoord; void main() { - gl_FragColor = texture2DRect(diffuseMap, vary_fragcoord.xy); + frag_color = texture2DRect(diffuseMap, vary_fragcoord.xy); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 179c721a2f..4d01eeb64e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect depthMap; @@ -126,7 +128,7 @@ void main() if (sa > 0.0) { - sa = texture2D(lightFunc,vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); + sa = 6 * texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); sa *= noise; col += da*sa*light_col[i].rgb*spec.rgb; } @@ -141,6 +143,6 @@ void main() discard; } - gl_FragColor.rgb = out_col; - gl_FragColor.a = 0.0; + frag_color.rgb = out_col; + frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 2196d14895..75de47614c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif //class 1 -- no shadows @@ -242,6 +244,6 @@ void main() } } - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; + frag_color.rgb = col; + frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl index 879942d8fa..62cfa5c316 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D alphaMap; @@ -52,5 +54,5 @@ void main() norm *= 0.5; norm += 0.5; - gl_FragColor = vec4(norm, alpha); + frag_color = vec4(norm, alpha); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index b673d00d6e..19800a8b8e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -107,7 +109,7 @@ void main() float sa = dot(normalize(lv-normalize(pos)),norm); if (sa > 0.0) { - sa = texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); + sa = 6 * texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0); sa *= noise; col += da*sa*color.rgb*spec.rgb; } @@ -118,6 +120,6 @@ void main() discard; } - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; + frag_color.rgb = col; + frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl index 18d451bf87..bf362e21a4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -122,5 +124,5 @@ void main() diff /= w; } - gl_FragColor = diff; + frag_color = diff; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl index c275434777..eb5beeef39 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -40,6 +42,6 @@ void main() vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res); - gl_FragColor = diff + bloom; + frag_color = diff + bloom; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl index 0d5c8e7287..bd0cb50464 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoTCV.glsl @@ -1,5 +1,5 @@ /** - * @file postgiV.glsl + * @file postDeferredV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,17 +24,17 @@ */ uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; +ATTRIBUTE vec3 position; VARYING vec2 vary_fragcoord; + uniform vec2 screen_res; void main() { //transform vertex vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = pos; + gl_Position = pos; vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl index 84d65d5b3b..96f9628424 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl @@ -24,8 +24,10 @@ */ #ifdef DEFINE_GL_FRAGCOLOR - out vec4 gl_FragColor; - #endif +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; @@ -96,5 +98,5 @@ void main() col = col*col*blur_quad.x + col*blur_quad.y + blur_quad.z; - gl_FragColor.rgb = col; + frag_color.rgb = col; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl index c1fb7b55d4..bced4a5577 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl @@ -24,14 +24,16 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif -uniform float minimum_alpha; - uniform sampler2D diffuseMap; -VARYING vec4 post_pos; +VARYING float pos_zd2; +VARYING float pos_w; +VARYING float target_pos_x; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; @@ -39,12 +41,20 @@ void main() { float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a; - if (alpha < minimum_alpha) + if (alpha < 0.05) // treat as totally transparent { discard; } - gl_FragColor = vec4(1,1,1,1); + if (alpha < 0.88) // treat as semi-transparent + { + if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25) + { + discard; + } + } + + frag_color = vec4(1,1,1,1); - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); + gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl index 7d3b06c56e..c1f2d90712 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl @@ -25,12 +25,15 @@ uniform mat4 texture_matrix0; uniform mat4 modelview_projection_matrix; +uniform float shadow_target_width; ATTRIBUTE vec3 position; ATTRIBUTE vec4 diffuse_color; ATTRIBUTE vec2 texcoord0; -VARYING vec4 post_pos; +VARYING float pos_zd2; +VARYING float pos_w; +VARYING float target_pos_x; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; @@ -39,8 +42,11 @@ void passTextureIndex(); void main() { //transform vertex - vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0); - post_pos = pos; + vec4 pre_pos = vec4(position.xyz, 1.0); + vec4 pos = modelview_projection_matrix * pre_pos; + target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x; + pos_w = pos.w; + pos_zd2 = pos.z * 0.5; gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl index bf75ca262e..7e55fdc12a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -24,14 +24,16 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 post_pos; void main() { - gl_FragColor = vec4(1,1,1,1); + frag_color = vec4(1,1,1,1); gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index 96ad0aa93a..faa54a316e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif ///////////////////////////////////////////////////////////////////////// @@ -57,8 +59,8 @@ void main() color *= 2.; /// Gamma correct for WL (soft clip effect). - gl_FragData[0] = vec4(scaleSoftClip(color.rgb), 1.0); - gl_FragData[1] = vec4(0.0,0.0,0.0,0.0); - gl_FragData[2] = vec4(0,0,1,0); + frag_data[0] = vec4(scaleSoftClip(color.rgb), 1.0); + frag_data[1] = vec4(0.0,0.0,0.0,0.0); + frag_data[2] = vec4(0,0,1,0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index 721de18e0b..7c02d31d43 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -26,7 +26,6 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; -ATTRIBUTE vec2 texcoord0; // SKY //////////////////////////////////////////////////////////////////////// // The vertex shader for creating the atmospheric sky @@ -34,7 +33,6 @@ ATTRIBUTE vec2 texcoord0; // Output parameters VARYING vec4 vary_HazeColor; -VARYING vec2 vary_texcoord0; // Inputs uniform vec3 camPosLocal; @@ -44,26 +42,23 @@ uniform vec4 sunlight_color; uniform vec4 ambient; uniform vec4 blue_horizon; uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; +uniform float haze_horizon; +uniform float haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 max_y; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y; uniform vec4 glow; uniform vec4 cloud_color; -uniform vec4 cloud_scale; - void main() { // World / view / projection gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_texcoord0 = texcoord0; - + // Get relative position vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0); //vec3 P = position.xyz + vec3(0,50,0); @@ -71,7 +66,7 @@ void main() // Set altitude if (P.y > 0.) { - P *= (max_y.x / P.y); + P *= (max_y / P.y); } else { @@ -93,12 +88,12 @@ void main() // Sunlight attenuation effect (hue and brightness) due to atmosphere // this is used later for sunlight modulation at various altitudes - light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); // Calculate relative weights - temp1 = blue_density + haze_density.x; + temp1 = blue_density + haze_density; blue_weight = blue_density / temp1; - haze_weight = haze_density.x / temp1; + haze_weight = haze_density / temp1; // Compute sunlight from P & lightnorm (for long rays like sky) temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); @@ -106,7 +101,7 @@ void main() sunlight *= exp( - light_atten * temp2.y); // Distance - temp2.z = Plen * density_multiplier.x; + temp2.z = Plen * density_multiplier; // Transparency (-> temp1) // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati @@ -131,20 +126,20 @@ void main() // Haze color above cloud vary_HazeColor = ( blue_horizon * blue_weight * (sunlight + ambient) - + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient) + + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient) ); // Increase ambient when there are more clouds vec4 tmpAmbient = ambient; - tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5; + tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; // Dim sunlight by cloud shadow percentage - sunlight *= (1. - cloud_shadow.x); + sunlight *= (1. - cloud_shadow); // Haze color below cloud vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient) - + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient) ); // Final atmosphere additive diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 51110ae4df..66e3cf6d13 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -51,12 +53,12 @@ uniform vec4 sunlight_color; uniform vec4 ambient; uniform vec4 blue_horizon; uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 distance_multiplier; -uniform vec4 max_y; +uniform float haze_horizon; +uniform float haze_density; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float distance_multiplier; +uniform float max_y; uniform vec4 glow; uniform float scene_light_strength; uniform mat3 env_mat; @@ -159,13 +161,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { //sunlight attenuation effect (hue and brightness) due to atmosphere //this is used later for sunlight modulation at various altitudes - light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); //I had thought blue_density and haze_density should have equal weighting, //but attenuation due to haze_density tends to seem too strong - temp1 = blue_density + vec4(haze_density.r); + temp1 = blue_density + vec4(haze_density); blue_weight = blue_density / temp1; - haze_weight = vec4(haze_density.r) / temp1; + haze_weight = vec4(haze_density) / temp1; //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) temp2.y = max(0.0, tmpLightnorm.y); @@ -173,12 +175,12 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { sunlight *= exp( - light_atten * temp2.y); // main atmospheric scattering line integral - temp2.z = Plen * density_multiplier.x; + temp2.z = Plen * density_multiplier; // Transparency (-> temp1) - // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati // compiler gets confused. - temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + temp1 = exp(-temp1 * temp2.z * distance_multiplier); //final atmosphere attenuation factor setAtmosAttenuation(temp1.rgb); @@ -199,7 +201,7 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { temp2.x += .25; //increase ambient when there are more clouds - vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5; /* decrease value and saturation (that in HSV, not HSL) for occluded areas * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html @@ -213,8 +215,8 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { //haze color setAdditiveColor( - vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) - + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x + tmpAmbient))); //brightness of surface both sunlight and ambient @@ -299,11 +301,11 @@ void main() // vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, sun_dir.xyz); - vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).r; + vec3 dumbshiny = vary_SunlitColor*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r); // add the two types of shiny together vec3 spec_contrib = dumbshiny * spec.rgb; - bloom = dot(spec_contrib, spec_contrib); + bloom = dot(spec_contrib, spec_contrib) / 4; col += spec_contrib; //add environmentmap @@ -322,7 +324,7 @@ void main() col = diffuse.rgb; } - gl_FragColor.rgb = col; + frag_color.rgb = col; - gl_FragColor.a = bloom; + frag_color.a = bloom; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index cc0f4e5b6b..7ed8ed3370 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -27,7 +27,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -184,6 +186,6 @@ void main() } } - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; + frag_color.rgb = col; + frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl index 03fccd2766..821058804c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif VARYING vec4 vertex_color; @@ -36,7 +38,7 @@ void main() { vec4 col = vertex_color * texture2D(diffuseMap, vary_texcoord0.xy); - gl_FragData[0] = col; - gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(0,0,1,0); + frag_data[0] = col; + frag_data[1] = vec4(0,0,0,0); + frag_data[2] = vec4(0,0,1,0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index adc7c5d005..5ca817aff6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -28,10 +28,12 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif void main() { - gl_FragColor = vec4(0,0,0,0); + frag_color = vec4(0,0,0,0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightNoFragCoordV.glsl index e5d3bb8ea6..47e9d15fbc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightNoFragCoordV.glsl @@ -1,5 +1,5 @@ /** - * @file giV.glsl + * @file sunLightF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,13 +24,8 @@ */ uniform mat4 modelview_projection_matrix; - + ATTRIBUTE vec3 position; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec2 texcoord0; - -VARYING vec4 vertex_color; -VARYING vec2 vary_fragcoord; uniform vec2 screen_res; @@ -39,10 +34,4 @@ void main() //transform vertex vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); gl_Position = pos; - - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; - vec4 tex = vec4(texcoord0,0,1); - tex.w = 1.0; - - vertex_color = diffuse_color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index fc5959a33c..2422d73a3e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif //class 1 -- no shadow, SSAO only @@ -37,8 +39,6 @@ uniform sampler2D noiseMap; // Inputs -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; uniform float ssao_radius; uniform float ssao_max_radius; uniform float ssao_factor; @@ -49,9 +49,6 @@ VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; -uniform float shadow_bias; -uniform float shadow_offset; - vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).r; @@ -128,8 +125,8 @@ void main() vec3 norm = texture2DRect(normalMap, pos_screen).xyz; norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm - gl_FragColor[0] = 1.0; - gl_FragColor[1] = calcAmbientOcclusion(pos, norm); - gl_FragColor[2] = 1.0; - gl_FragColor[3] = 1.0; + frag_color[0] = 1.0; + frag_color[1] = calcAmbientOcclusion(pos, norm); + frag_color[2] = 1.0; + frag_color[3] = 1.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 5522e6c41d..8a5e482e80 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif uniform sampler2D detail_0; @@ -51,9 +53,9 @@ void main() float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a; vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); - gl_FragData[0] = vec4(outColor.rgb, 0.0); - gl_FragData[1] = vec4(0,0,0,0); + frag_data[0] = vec4(outColor.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index ea98d6884c..6cf6106b51 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif uniform sampler2D diffuseMap; @@ -43,8 +45,8 @@ void main() discard; } - gl_FragData[0] = vec4(vertex_color.rgb*col.rgb, 0.0); - gl_FragData[1] = vec4(0,0,0,0); + frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl index 20d0170535..d4d2f5f571 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -43,7 +45,7 @@ void main() discard; } - gl_FragColor = vec4(1,1,1,1); + frag_color = vec4(1,1,1,1); gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 4c9ea24a24..42dc7c0980 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragData[3]; +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData #endif vec3 scaleSoftClip(vec3 inColor); @@ -157,7 +159,7 @@ void main() //wavef = normalize(wavef); vec3 screenspacewavef = (norm_mat*vec4(wavef, 1.0)).xyz; - gl_FragData[0] = vec4(color.rgb, 0.5); // diffuse - gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec - gl_FragData[2] = vec4(screenspacewavef.xy*0.5+0.5, screenspacewavef.z, screenspacewavef.z*0.5); // normalxyz, displace + frag_data[0] = vec4(color.rgb, 0.5); // diffuse + frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec + frag_data[2] = vec4(screenspacewavef.xy*0.5+0.5, screenspacewavef.z, screenspacewavef.z*0.5); // normalxyz, displace } diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index 9a3d792224..0f5eb288fd 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseMap; @@ -46,7 +48,7 @@ void main() float lum = smoothstep(minLuminance, minLuminance+1.0, dot(col.rgb, lumWeights ) ); float warmth = smoothstep(minLuminance, minLuminance+1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); - gl_FragColor.rgb = col.rgb; - gl_FragColor.a = max(col.a, mix(lum, warmth, warmthAmount) * maxExtractAlpha); + frag_color.rgb = col.rgb; + frag_color.a = max(col.a, mix(lum, warmth, warmthAmount) * maxExtractAlpha); } diff --git a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl index 90bb84323c..c1f6af9f57 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D diffuseMap; @@ -54,5 +56,5 @@ void main() col += kern[6] * texture2D(diffuseMap, vary_texcoord2.zw); col += kern[7] * texture2D(diffuseMap, vary_texcoord3.zw); - gl_FragColor = vec4(col.rgb * glowStrength, col.a); + frag_color = vec4(col.rgb * glowStrength, col.a); } diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl index 18f6d91804..668a710c04 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -59,6 +61,6 @@ void main() /// Add WL Components outColor.rgb = atmosLighting(outColor.rgb * vertex_color.rgb); - gl_FragColor = vec4(scaleSoftClip(outColor.rgb), 1.0); + frag_color = vec4(scaleSoftClip(outColor.rgb), 1.0); } diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl index e5c7ced52c..a956562396 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -60,6 +62,6 @@ void main() outColor.rgb = atmosLighting(outColor.rgb * vertex_color.rgb); outColor = applyWaterFog(outColor); - gl_FragColor = outColor; + frag_color = outColor; } diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl index 1fdb90f792..0d8dab0a41 100644 --- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D diffuseMap; @@ -106,5 +108,5 @@ void main() vec4 fb = texture2D(screenTex, distort); - gl_FragColor = applyWaterFog(fb,view.xyz); + frag_color = applyWaterFog(fb,view.xyz); } diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl index 444c896d38..79bffab745 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif vec3 scaleSoftClip(vec3 inColor); @@ -135,5 +137,5 @@ void main() color.rgb = scaleSoftClip(color.rgb); color.a = spec * sunAngle2; - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/interface/alphamaskF.glsl b/indra/newview/app_settings/shaders/class1/interface/alphamaskF.glsl index d2f5e1987a..f520f301d9 100644 --- a/indra/newview/app_settings/shaders/class1/interface/alphamaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/alphamaskF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D diffuseMap; @@ -42,5 +44,5 @@ void main() discard; } - gl_FragColor = col; + frag_color = col; } diff --git a/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl index 4b481ba834..a96d04cc39 100644 --- a/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D diffuseMap; @@ -38,5 +40,5 @@ void main() { vec4 color = vertex_color*texture2D(diffuseMap, vary_texcoord0.xy); color.a *= custom_alpha; - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/interface/debugF.glsl b/indra/newview/app_settings/shaders/class1/interface/debugF.glsl index 6bcc97ba18..67c6baddbb 100644 --- a/indra/newview/app_settings/shaders/class1/interface/debugF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/debugF.glsl @@ -24,12 +24,14 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform vec4 color; void main() { - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl index f67703b839..ed803de277 100644 --- a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif #extension GL_ARB_texture_rectangle : enable @@ -37,6 +39,6 @@ VARYING vec2 vary_texcoord1; void main() { - gl_FragColor = texture2D(glowMap, vary_texcoord0.xy) + + frag_color = texture2D(glowMap, vary_texcoord0.xy) + texture2DRect(screenMap, vary_texcoord1.xy); } diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl index c66a6e5b48..59520bb99f 100644 --- a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -38,5 +40,5 @@ void main() { vec3 col = texture2DRect(diffuseRect, vary_tc*screen_res).rgb; - gl_FragColor = vec4(col.rgb, dot(col.rgb, vec3(0.299, 0.587, 0.144))); + frag_color = vec4(col.rgb, dot(col.rgb, vec3(0.299, 0.587, 0.144))); } diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl index ecbc30f05f..6cc9bbbea2 100644 --- a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform vec4 color; @@ -34,5 +36,5 @@ VARYING vec2 vary_texcoord0; void main() { - gl_FragColor = color*texture2D(diffuseMap, vary_texcoord0.xy); + frag_color = color*texture2D(diffuseMap, vary_texcoord0.xy); } diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl index 85f819f4c2..db130e456c 100644 --- a/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl @@ -24,10 +24,12 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif void main() { - gl_FragColor = vec4(1,1,1,1); + frag_color = vec4(1,1,1,1); } diff --git a/indra/newview/app_settings/shaders/class1/interface/onetexturenocolorF.glsl b/indra/newview/app_settings/shaders/class1/interface/onetexturenocolorF.glsl index fafeb5a7b4..415181126b 100644 --- a/indra/newview/app_settings/shaders/class1/interface/onetexturenocolorF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/onetexturenocolorF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D tex0; @@ -33,5 +35,5 @@ VARYING vec2 vary_texcoord0; void main() { - gl_FragColor = texture2D(tex0, vary_texcoord0.xy); + frag_color = texture2D(tex0, vary_texcoord0.xy); } diff --git a/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl index f790122749..67dc500493 100644 --- a/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D tex0; @@ -36,5 +38,5 @@ void main() { float alpha = texture2D(tex0, vary_texcoord0.xy).a * vertex_color.a; - gl_FragColor = vec4(vertex_color.rgb, alpha); + frag_color = vec4(vertex_color.rgb, alpha); } diff --git a/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl b/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl index a0bb255cfa..772bb374e8 100644 --- a/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/splattexturerectF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect screenMap; @@ -36,5 +38,5 @@ VARYING vec2 vary_texcoord0; void main() { - gl_FragColor = texture2DRect(screenMap, vary_texcoord0.xy) * vertex_color; + frag_color = texture2DRect(screenMap, vary_texcoord0.xy) * vertex_color; } diff --git a/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl b/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl index cdb48163dd..95679e93e7 100644 --- a/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D tex0; @@ -35,5 +37,5 @@ VARYING vec2 vary_texcoord1; void main() { - gl_FragColor = texture2D(tex0, vary_texcoord0.xy)+texture2D(tex1, vary_texcoord1.xy); + frag_color = texture2D(tex0, vary_texcoord0.xy)+texture2D(tex1, vary_texcoord1.xy); } diff --git a/indra/newview/app_settings/shaders/class1/interface/uiF.glsl b/indra/newview/app_settings/shaders/class1/interface/uiF.glsl index 36d6e06fc5..299bfb72aa 100644 --- a/indra/newview/app_settings/shaders/class1/interface/uiF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/uiF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D diffuseMap; @@ -34,5 +36,5 @@ VARYING vec4 vertex_color; void main() { - gl_FragColor = vertex_color*texture2D(diffuseMap, vary_texcoord0.xy); + frag_color = vertex_color*texture2D(diffuseMap, vary_texcoord0.xy); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl index 10413bdeb0..cf29939cb2 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -48,6 +50,6 @@ void default_lighting() color.rgb = scaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl index 1164e5b0a6..4070d41f47 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -50,6 +52,6 @@ void default_lighting() color.rgb = scaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl index 735f5b3813..d6ebfcb825 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -41,6 +43,6 @@ void default_lighting() color.rgb = scaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl index ba99c0ed71..6c34643aab 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -48,6 +50,6 @@ void fullbright_lighting() color.rgb = fullbrightScaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl index c3edc0bd70..2ff7f795b0 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -41,6 +43,6 @@ void fullbright_lighting() color.rgb = fullbrightScaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl index 276fad4f44..f4477bd29a 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -50,6 +52,6 @@ void fullbright_lighting() color.rgb = fullbrightScaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedF.glsl index 4e1e664e6b..2738ff8947 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -43,6 +45,6 @@ void fullbright_lighting() color.rgb = fullbrightScaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl index c981e9eba2..777c8b45bb 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -50,6 +52,6 @@ void fullbright_shiny_lighting() color.a = max(color.a, vertex_color.a); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyNonIndexedF.glsl index a4893f0359..4fa3b1d939 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -51,6 +53,6 @@ void fullbright_shiny_lighting() color.a = max(color.a, vertex_color.a); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl index c10cde98e0..58984a4263 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl @@ -23,7 +23,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -48,6 +50,6 @@ void fullbright_shiny_lighting_water() color.rgb = fullbrightScaleSoftClip(color.rgb); color.a = max(color.a, vertex_color.a); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterNonIndexedF.glsl index e9b26087f4..a39b7205d7 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterNonIndexedF.glsl @@ -23,7 +23,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -49,6 +51,6 @@ void fullbright_shiny_lighting_water() color.rgb = fullbrightScaleSoftClip(color.rgb); color.a = max(color.a, vertex_color.a); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl index 754b2922d9..99a6fe85fe 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -48,6 +50,6 @@ void fullbright_lighting_water() color.rgb = fullbrightAtmosTransport(color.rgb); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl index 2547f9e750..df182168f3 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -41,6 +43,6 @@ void fullbright_lighting_water() color.rgb = fullbrightAtmosTransport(color.rgb); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl index f69b907dc7..63f92a8844 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -48,6 +50,6 @@ void fullbright_lighting_water() color.rgb = fullbrightAtmosTransport(color.rgb); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedF.glsl index aa3ef8cdd9..0e68091e7c 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -41,6 +43,6 @@ void fullbright_lighting_water() color.rgb = fullbrightAtmosTransport(color.rgb); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightNonIndexedF.glsl index 9f1a358b53..0aca768021 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -43,6 +45,6 @@ void default_lighting() color.rgb = scaleSoftClip(color.rgb); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl index e9c27dbefd..52e3b2ad02 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -49,6 +51,6 @@ void shiny_lighting() color.rgb = scaleSoftClip(color.rgb); color.a = max(color.a, vertex_color.a); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyNonIndexedF.glsl index 595ad74365..474d5ea496 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -50,6 +52,6 @@ void shiny_lighting() color.rgb = scaleSoftClip(color.rgb); color.a = max(color.a, vertex_color.a); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl index 68c727d62c..d2a4c47aac 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -46,6 +48,6 @@ void shiny_lighting_water() color.rgb = atmosLighting(color.rgb); color.a = max(color.a, vertex_color.a); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterNonIndexedF.glsl index f32b9e1958..f3bd662364 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -47,6 +49,6 @@ void shiny_lighting_water() color.rgb = atmosLighting(color.rgb); color.a = max(color.a, vertex_color.a); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl index 103dd633c9..b68240ba0d 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -46,6 +48,6 @@ void default_lighting_water() color.rgb = atmosLighting(color.rgb); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl index bef72752da..da3b20012d 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -50,6 +52,6 @@ void default_lighting_water() color = applyWaterFog(color); - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl index e9537d1e9d..00609e93cd 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl @@ -24,8 +24,10 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; -#endif +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; @@ -39,6 +41,6 @@ void default_lighting_water() color.rgb = atmosLighting(color.rgb); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterNonIndexedF.glsl index 8b0c25b705..13ecb7a636 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterNonIndexedF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -41,6 +43,6 @@ void default_lighting_water() color.rgb = atmosLighting(color.rgb); - gl_FragColor = applyWaterFog(color); + frag_color = applyWaterFog(color); } diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl index 4b85d61aca..d55f0db530 100644 --- a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2D texture0; @@ -38,5 +40,5 @@ void main() float tex0 = texture2D(texture0, vary_texcoord0.xy).a; float tex1 = texture2D(texture1, vary_texcoord1.xy).a; - gl_FragColor = vec4(tex0+(1.0-tex1)-0.5); + frag_color = vec4(tex0+(1.0-tex1)-0.5); } diff --git a/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl b/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl index 3c6e22b295..add437d144 100644 --- a/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform float minimum_alpha; @@ -42,5 +44,5 @@ void main() discard; } - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl b/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl index a95c9e0ab9..7c0699d72f 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 float texture_index; +ATTRIBUTE ivec4 texture_index; -VARYING float vary_texture_index; +VARYING_FLAT ivec4 vary_texture_index; void passTextureIndex() { diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 1179b212ae..8db4cb58cf 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -56,20 +58,22 @@ uniform float shadow_bias; uniform mat4 inv_proj; -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) { stc.xyz /= stc.w; stc.z += shadow_bias; + + stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); - - return shadow/5.0; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; + + return shadow*0.2; } @@ -78,7 +82,7 @@ void main() vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - float shadow = 1.0; + float shadow = 0.0; vec4 pos = vec4(vary_position, 1.0); vec4 spos = pos; @@ -87,31 +91,65 @@ void main() { vec4 lpos; - if (spos.z < -shadow_clip.z) + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap3, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap3, lpos)*w; + weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } - else if (spos.z < -shadow_clip.y) + + if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap2, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap2, lpos)*w; + weight += w; } - else if (spos.z < -shadow_clip.x) + + if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap1, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadow(shadowMap1, lpos)*w; + weight += w; } - else + + if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap0, lpos, 1.5); + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadow(shadowMap0, lpos)*w; + weight += w; } + + + shadow /= weight; + } + else + { + shadow = 1.0; } vec4 diff = diffuseLookup(vary_texcoord0.xy); @@ -125,6 +163,6 @@ void main() color.rgb += diff.rgb * vary_pointlight_col.rgb; - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl index 0df557f2aa..33958a5010 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRectShadow shadowMap0; @@ -69,20 +71,22 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) { stc.xyz /= stc.w; stc.z += shadow_bias; + + stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); - - return shadow/5.0; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; + + return shadow*0.2; } @@ -91,7 +95,7 @@ void main() vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - float shadow = 1.0; + float shadow = 0.0; vec4 pos = vec4(vary_position, 1.0); vec4 spos = pos; @@ -100,33 +104,68 @@ void main() { vec4 lpos; - if (spos.z < -shadow_clip.z) + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap3, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap3, lpos)*w; + weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } - else if (spos.z < -shadow_clip.y) + + if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap2, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap2, lpos)*w; + weight += w; } - else if (spos.z < -shadow_clip.x) + + if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap1, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadow(shadowMap1, lpos)*w; + weight += w; } - else + + if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap0, lpos, 1.5); + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadow(shadowMap0, lpos)*w; + weight += w; } + + + shadow /= weight; + } - + else + { + shadow = 1.0; + } + vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, vertex_color.a); @@ -138,6 +177,6 @@ void main() color.rgb += diff.rgb * vary_pointlight_col.rgb; - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl index 331dbc7079..ba6f3ace53 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRectShadow shadowMap0; @@ -68,20 +70,22 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc) { stc.xyz /= stc.w; stc.z += shadow_bias; + + stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); - - return shadow/5.0; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; + + return shadow*0.2; } @@ -90,7 +94,7 @@ void main() vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - float shadow = 1.0; + float shadow = 0.0; vec4 pos = vec4(vary_position, 1.0); vec4 spos = pos; @@ -99,31 +103,65 @@ void main() { vec4 lpos; - if (spos.z < -shadow_clip.z) + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap3, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap3, lpos)*w; + weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } - else if (spos.z < -shadow_clip.y) + + if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap2, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap2, lpos)*w; + weight += w; } - else if (spos.z < -shadow_clip.x) + + if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap1, lpos, 1.5); + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadow(shadowMap1, lpos)*w; + weight += w; } - else + + if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap0, lpos, 1.5); + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadow(shadowMap0, lpos)*w; + weight += w; } + + + shadow /= weight; + } + else + { + shadow = 1.0; } vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); @@ -137,6 +175,6 @@ void main() color.rgb += diff.rgb * vary_pointlight_col.rgb; - gl_FragColor = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl index 83815b1786..9629cfe824 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl @@ -61,6 +61,12 @@ uniform vec3 light_direction[8]; uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) { //get light vector diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 1660f9687e..1586aab0f2 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -63,6 +63,12 @@ uniform vec3 light_direction[8]; uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) { //get light vector diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index 84c27edb26..44aaa98b97 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -60,6 +60,12 @@ uniform vec3 light_direction[8]; uniform vec3 light_attenuation[8]; uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) { //get light vector diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 14a683971a..f7f1f649ce 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -253,6 +255,6 @@ void main() } } - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; + frag_color.rgb = col; + frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 97f3063a9e..a137bea30f 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif uniform sampler2DRect diffuseRect; @@ -51,12 +53,12 @@ uniform vec4 sunlight_color; uniform vec4 ambient; uniform vec4 blue_horizon; uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 distance_multiplier; -uniform vec4 max_y; +uniform float haze_horizon; +uniform float haze_density; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float distance_multiplier; +uniform float max_y; uniform vec4 glow; uniform float scene_light_strength; uniform mat3 env_mat; @@ -161,13 +163,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { //sunlight attenuation effect (hue and brightness) due to atmosphere //this is used later for sunlight modulation at various altitudes - light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); //I had thought blue_density and haze_density should have equal weighting, //but attenuation due to haze_density tends to seem too strong - temp1 = blue_density + vec4(haze_density.r); + temp1 = blue_density + vec4(haze_density); blue_weight = blue_density / temp1; - haze_weight = vec4(haze_density.r) / temp1; + haze_weight = vec4(haze_density) / temp1; //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) temp2.y = max(0.0, tmpLightnorm.y); @@ -175,12 +177,12 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { sunlight *= exp( - light_atten * temp2.y); // main atmospheric scattering line integral - temp2.z = Plen * density_multiplier.x; + temp2.z = Plen * density_multiplier; // Transparency (-> temp1) - // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati // compiler gets confused. - temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + temp1 = exp(-temp1 * temp2.z * distance_multiplier); //final atmosphere attenuation factor setAtmosAttenuation(temp1.rgb); @@ -201,7 +203,7 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { temp2.x += .25; //increase ambient when there are more clouds - vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5; /* decrease value and saturation (that in HSV, not HSL) for occluded areas * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html @@ -215,8 +217,8 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { //haze color setAdditiveColor( - vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) - + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x + tmpAmbient))); //brightness of surface both sunlight and ambient @@ -307,11 +309,11 @@ void main() // vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, sun_dir.xyz); - vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).r; + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r); // add the two types of shiny together vec3 spec_contrib = dumbshiny * spec.rgb; - bloom = dot(spec_contrib, spec_contrib); + bloom = dot(spec_contrib, spec_contrib) / 4; col += spec_contrib; //add environmentmap @@ -330,6 +332,6 @@ void main() col = diffuse.rgb; } - gl_FragColor.rgb = col; - gl_FragColor.a = bloom; + frag_color.rgb = col; + frag_color.a = bloom; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 31bd0c79da..99a277fbfc 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif VARYING vec4 vertex_color; @@ -201,6 +203,6 @@ void main() } } - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; + frag_color.rgb = col; + frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 229c2f4b67..db3d760359 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -26,7 +26,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif //class 2, shadows, no SSAO @@ -76,42 +78,42 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += shadow_bias*scl; - + + stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); // add some jitter to X sample pos according to Y to disguise the snapping going on here + float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, -1.5, 0.0)).x; - return shadow/5.0; - - //return shadow; + return shadow*0.2; } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; + stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; - vec2 off = 1.5/proj_shadow_res; + vec2 off = 1.0/proj_shadow_res; + off.y *= 1.5; - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); - - return shadow/5.0; - - //return shadow; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; + + return shadow*0.2; } void main() @@ -129,11 +131,11 @@ void main() /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { - gl_FragColor = vec4(0.0); // doesn't matter + frag_color = vec4(0.0); // doesn't matter return; }*/ - float shadow = 1.0; + float shadow = 0.0; float dp_directional_light = max(0.0, dot(norm, sun_dir.xyz)); vec3 shadow_pos = pos.xyz + displace*norm; @@ -152,32 +154,62 @@ void main() { vec4 lpos; - if (spos.z < -shadow_clip.z) + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap3, lpos, 0.25); + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; + weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } - else if (spos.z < -shadow_clip.y) + + if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap2, lpos, 0.5); + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w; + weight += w; } - else if (spos.z < -shadow_clip.x) + + if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap1, lpos, 0.75); + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w; + weight += w; } - else + + if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap0, lpos, 1.0); + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w; + weight += w; } + + shadow /= weight; + // take the most-shadowed value out of these two: // * the blurred sun shadow in the light (shadow) map // * an unblurred dot product between the sun and this norm @@ -198,19 +230,19 @@ void main() shadow = 1.0; } - gl_FragColor[0] = shadow; - gl_FragColor[1] = 1.0; + frag_color[0] = shadow; + frag_color[1] = 1.0; spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0); //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); + frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); + frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen); - //gl_FragColor.rgb = pos.xyz; - //gl_FragColor.b = shadow; + //frag_color.rgb = pos.xyz; + //frag_color.b = shadow; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index 6b420833b9..dfe108eb01 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -25,7 +25,9 @@ #extension GL_ARB_texture_rectangle : enable #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif //class 2 -- shadows and SSAO @@ -88,7 +90,7 @@ vec2 getKern(int i) kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - + return kern[i]; } @@ -137,42 +139,42 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) return min(ret, 1.0); } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += shadow_bias*scl; + + stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; - - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); - - return shadow/5.0; - //return shadow; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x; + shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x; + + return shadow*0.2; } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; + stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; - vec2 off = 1.5/proj_shadow_res; - - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); - shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); + vec2 off = 1.0/proj_shadow_res; + off.y *= 1.5; - return shadow/5.0; - - //return shadow; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; + + return shadow*0.2; } void main() @@ -190,11 +192,11 @@ void main() /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { - gl_FragColor = vec4(0.0); // doesn't matter + frag_color = vec4(0.0); // doesn't matter return; }*/ - float shadow = 1.0; + float shadow = 0.0; float dp_directional_light = max(0.0, dot(norm, sun_dir.xyz)); vec3 shadow_pos = pos.xyz + displace*norm; @@ -212,33 +214,63 @@ void main() else { vec4 lpos; - - if (spos.z < -shadow_clip.z) + + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap3, lpos, 0.25); + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; + weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } - else if (spos.z < -shadow_clip.y) + + if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap2, lpos, 0.5); + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w; + weight += w; } - else if (spos.z < -shadow_clip.x) + + if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap1, lpos, 0.75); + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w; + weight += w; } - else + + if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; lpos.xy *= shadow_res; - shadow = pcfShadow(shadowMap0, lpos, 1.0); + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w; + weight += w; } + + shadow /= weight; + // take the most-shadowed value out of these two: // * the blurred sun shadow in the light (shadow) map // * an unblurred dot product between the sun and this norm @@ -259,19 +291,19 @@ void main() shadow = 1.0; } - gl_FragColor[0] = shadow; - gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + frag_color[0] = shadow; + frag_color[1] = calcAmbientOcclusion(pos, norm); spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0); //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); + frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); + frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen); - //gl_FragColor.rgb = pos.xyz; - //gl_FragColor.b = shadow; + //frag_color.rgb = pos.xyz; + //frag_color.b = shadow; } diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl index 6a83be1426..da3d922017 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl @@ -47,12 +47,12 @@ uniform vec4 sunlight_color; uniform vec4 ambient; uniform vec4 blue_horizon; uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 distance_multiplier; -uniform vec4 max_y; +uniform float haze_horizon; +uniform float haze_density; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float distance_multiplier; +uniform float max_y; uniform vec4 glow; void calcAtmospherics(vec3 inPositionEye) { @@ -61,8 +61,8 @@ void calcAtmospherics(vec3 inPositionEye) { setPositionEye(P); //(TERRAIN) limit altitude - if (P.y > max_y.x) P *= (max_y.x / P.y); - if (P.y < -max_y.x) P *= (-max_y.x / P.y); + if (P.y > max_y) P *= (max_y / P.y); + if (P.y < -max_y) P *= (-max_y / P.y); vec3 tmpLightnorm = lightnorm.xyz; @@ -78,13 +78,13 @@ void calcAtmospherics(vec3 inPositionEye) { //sunlight attenuation effect (hue and brightness) due to atmosphere //this is used later for sunlight modulation at various altitudes - light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); //I had thought blue_density and haze_density should have equal weighting, //but attenuation due to haze_density tends to seem too strong - temp1 = blue_density + vec4(haze_density.r); + temp1 = blue_density + vec4(haze_density); blue_weight = blue_density / temp1; - haze_weight = vec4(haze_density.r) / temp1; + haze_weight = vec4(haze_density) / temp1; //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) temp2.y = max(0.0, tmpLightnorm.y); @@ -92,12 +92,12 @@ void calcAtmospherics(vec3 inPositionEye) { sunlight *= exp( - light_atten * temp2.y); // main atmospheric scattering line integral - temp2.z = Plen * density_multiplier.x; + temp2.z = Plen * density_multiplier; // Transparency (-> temp1) - // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati // compiler gets confused. - temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + temp1 = exp(-temp1 * temp2.z * distance_multiplier); //final atmosphere attenuation factor setAtmosAttenuation(temp1.rgb); @@ -122,12 +122,12 @@ void calcAtmospherics(vec3 inPositionEye) { //increase ambient when there are more clouds - vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5; //haze color setAdditiveColor( - vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) - + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x + tmpAmbient))); //brightness of surface both sunlight and ambient diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl index 4ab06c6e21..96c70651b1 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif ///////////////////////////////////////////////////////////////////////// @@ -96,7 +98,7 @@ void main() color *= 2.; /// Gamma correct for WL (soft clip effect). - gl_FragColor.rgb = scaleSoftClip(color.rgb); - gl_FragColor.a = alpha1; + frag_color.rgb = scaleSoftClip(color.rgb); + frag_color.a = alpha1; } diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl index c5bb52169c..c1dd45cd67 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl @@ -49,18 +49,18 @@ uniform vec4 sunlight_color; uniform vec4 ambient; uniform vec4 blue_horizon; uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; +uniform float haze_horizon; +uniform float haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 max_y; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y; uniform vec4 glow; uniform vec4 cloud_color; -uniform vec4 cloud_scale; +uniform float cloud_scale; void main() { @@ -76,7 +76,7 @@ void main() // Set altitude if (P.y > 0.) { - P *= (max_y.x / P.y); + P *= (max_y / P.y); } else { @@ -98,12 +98,12 @@ void main() // Sunlight attenuation effect (hue and brightness) due to atmosphere // this is used later for sunlight modulation at various altitudes - light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); // Calculate relative weights - temp1 = blue_density + haze_density.x; + temp1 = blue_density + haze_density; blue_weight = blue_density / temp1; - haze_weight = haze_density.x / temp1; + haze_weight = haze_density / temp1; // Compute sunlight from P & lightnorm (for long rays like sky) temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); @@ -111,7 +111,7 @@ void main() sunlight *= exp( - light_atten * temp2.y); // Distance - temp2.z = Plen * density_multiplier.x; + temp2.z = Plen * density_multiplier; // Transparency (-> temp1) // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati @@ -135,14 +135,14 @@ void main() // Increase ambient when there are more clouds vec4 tmpAmbient = ambient; - tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5; + tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; // Dim sunlight by cloud shadow percentage - sunlight *= (1. - cloud_shadow.x); + sunlight *= (1. - cloud_shadow); // Haze color below cloud vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient) - + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient) ); // CLOUDS @@ -163,13 +163,13 @@ void main() vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1); // Make a nice cloud density based on the cloud_shadow value that was passed in. - vary_CloudDensity = 2. * (cloud_shadow.x - 0.25); + vary_CloudDensity = 2. * (cloud_shadow - 0.25); // Texture coords vary_texcoord0 = texcoord0; vary_texcoord0.xy -= 0.5; - vary_texcoord0.xy /= cloud_scale.x; + vary_texcoord0.xy /= cloud_scale; vary_texcoord0.xy += 0.5; vary_texcoord1 = vary_texcoord0; diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl index c9d96b2cf4..e2a2367626 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl @@ -24,7 +24,9 @@ */ #ifdef DEFINE_GL_FRAGCOLOR -out vec4 gl_FragColor; +out vec4 frag_color; +#else +#define frag_color gl_FragColor #endif ///////////////////////////////////////////////////////////////////////// @@ -57,7 +59,7 @@ void main() color *= 2.; /// Gamma correct for WL (soft clip effect). - gl_FragColor.rgb = scaleSoftClip(color.rgb); - gl_FragColor.a = 1.0; + frag_color.rgb = scaleSoftClip(color.rgb); + frag_color.a = 1.0; } diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl index 46773cf89f..3788ddaf2d 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl @@ -42,19 +42,17 @@ uniform vec4 sunlight_color; uniform vec4 ambient; uniform vec4 blue_horizon; uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; +uniform float haze_horizon; +uniform float haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 max_y; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y; uniform vec4 glow; uniform vec4 cloud_color; -uniform vec4 cloud_scale; - void main() { @@ -68,7 +66,7 @@ void main() // Set altitude if (P.y > 0.) { - P *= (max_y.x / P.y); + P *= (max_y / P.y); } else { @@ -87,15 +85,14 @@ void main() vec4 sunlight = sunlight_color; vec4 light_atten; - // Sunlight attenuation effect (hue and brightness) due to atmosphere // this is used later for sunlight modulation at various altitudes - light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); + light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); // Calculate relative weights - temp1 = blue_density + haze_density.x; + temp1 = blue_density + haze_density; blue_weight = blue_density / temp1; - haze_weight = haze_density.x / temp1; + haze_weight = haze_density / temp1; // Compute sunlight from P & lightnorm (for long rays like sky) temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); @@ -103,7 +100,7 @@ void main() sunlight *= exp( - light_atten * temp2.y); // Distance - temp2.z = Plen * density_multiplier.x; + temp2.z = Plen * density_multiplier; // Transparency (-> temp1) // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati @@ -128,20 +125,20 @@ void main() // Haze color above cloud vary_HazeColor = ( blue_horizon * blue_weight * (sunlight + ambient) - + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient) + + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient) ); // Increase ambient when there are more clouds vec4 tmpAmbient = ambient; - tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5; + tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; // Dim sunlight by cloud shadow percentage - sunlight *= (1. - cloud_shadow.x); + sunlight *= (1. - cloud_shadow); // Haze color below cloud vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient) - + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) + + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient) ); // Final atmosphere additive diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 0f33d40ac3..e8a109e661 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -42,7 +42,6 @@ RenderGamma 1 0 RenderGlowResolutionPow 1 9 RenderGround 1 1 RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 RenderObjectBump 1 1 RenderLocalLights 1 1 RenderReflectionDetail 1 4 @@ -62,6 +61,7 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -73,6 +73,38 @@ RenderMaxTextureIndex 1 16 // +// Low Graphics Settings (fixed function) +// +list LowFixedFunction +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderLocalLights 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 1.125 +VertexShaderEnable 1 0 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderFSAASamples 1 0 + + +// // Low Graphics Settings // list Low @@ -95,7 +127,7 @@ RenderTransparentWater 1 0 RenderTreeLODFactor 1 0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -VertexShaderEnable 1 0 +VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 RenderDeferred 1 0 @@ -224,6 +256,12 @@ list Class3 RenderVBOEnable 1 1 // +// VRAM > 512MB +// +list VRAMGT512 +RenderCompressTextures 1 0 + +// // No Pixel Shaders available // list NoPixelShaders @@ -303,6 +341,7 @@ RenderMaxTextureIndex 1 1 list Intel RenderAnisotropic 1 0 RenderVBOEnable 1 0 +RenderFSAASamples 1 0 list GeForce2 RenderAnisotropic 1 0 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 8142311a55..3a0e7e3697 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -43,7 +43,6 @@ RenderGlowResolutionPow 1 9 RenderGround 1 1 RenderLocalLights 1 1 RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 RenderObjectBump 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 @@ -62,6 +61,7 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -70,6 +70,37 @@ RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 // +// Low Graphics Settings (fixed function) +// +list LowFixedFunction +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderLocalLights 1 0 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 0.5 +VertexShaderEnable 1 1 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderFSAASamples 1 0 + +// // Low Graphics Settings // list Low @@ -221,6 +252,12 @@ list Class3 RenderVBOEnable 1 1 // +// VRAM > 512MB +// +list VRAMGT512 +RenderCompressTextures 1 0 + +// // No Pixel Shaders available // list NoPixelShaders @@ -292,10 +329,15 @@ RenderObjectBump 0 0 list OpenGLPre15 RenderVBOEnable 1 0 +list OpenGLPre30 +RenderDeferred 0 0 +RenderMaxTextureIndex 1 1 + list Intel RenderAnisotropic 1 0 // Avoid some Intel crashes on Linux RenderCubeMap 0 0 +RenderFSAASamples 1 0 list GeForce2 RenderAnisotropic 1 0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 942c043081..96362ff4bb 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -43,7 +43,6 @@ RenderGlowResolutionPow 1 9 RenderGround 1 1 RenderLocalLights 1 1 RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 RenderObjectBump 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 @@ -62,6 +61,7 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 0.5 +RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -72,6 +72,37 @@ RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 // +// Low Graphics Settings (fixed function) +// +list LowFixedFunction +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderLocalLights 1 0 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 0.5 +VertexShaderEnable 1 0 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderFSAASamples 1 0 + +// // Low Graphics Settings // list Low @@ -94,7 +125,7 @@ RenderTransparentWater 1 0 RenderTreeLODFactor 1 0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 -VertexShaderEnable 1 0 +VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 RenderDeferred 1 0 @@ -249,6 +280,12 @@ RenderDeferredSSAO 0 0 RenderShadowDetail 0 0 // +// VRAM > 512MB +// +list VRAMGT512 +RenderCompressTextures 1 0 + +// // "Default" setups for safe, low, medium, high // list safe @@ -287,6 +324,7 @@ RenderObjectBump 0 0 list OpenGLPre15 RenderVBOEnable 1 0 + list TexUnit8orLess RenderDeferredSSAO 0 0 @@ -296,6 +334,7 @@ RenderDeferredSSAO 1 0 list Intel RenderAnisotropic 1 0 RenderLocalLights 1 0 +RenderFSAASamples 1 0 list GeForce2 RenderAnisotropic 1 0 diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt index 278d601860..398a64378e 100644 --- a/indra/newview/featuretable_xp.txt +++ b/indra/newview/featuretable_xp.txt @@ -43,7 +43,6 @@ RenderGlowResolutionPow 1 9 RenderGround 1 1 RenderLocalLights 1 1 RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 RenderObjectBump 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 @@ -62,6 +61,7 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 0 RenderDeferredSSAO 1 0 @@ -72,6 +72,37 @@ RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 // +// Low Graphics Settings (fixed function) +// +list LowFixedFunction +RenderAnisotropic 1 0 +RenderAvatarCloth 1 0 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 +RenderAvatarVP 1 0 +RenderFarClip 1 64 +RenderFlexTimeFactor 1 0 +RenderGlowResolutionPow 1 8 +RenderLocalLights 1 0 +RenderMaxPartCount 1 0 +RenderObjectBump 1 0 +RenderReflectionDetail 1 0 +RenderTerrainDetail 1 0 +RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 +RenderTreeLODFactor 1 0 +RenderUseImpostors 1 1 +RenderVolumeLODFactor 1 0.5 +VertexShaderEnable 1 0 +WindLightUseAtmosShaders 1 0 +WLSkyDetail 1 48 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderFSAASamples 1 0 + +// // Low Graphics Settings // list Low @@ -94,7 +125,7 @@ RenderTransparentWater 1 0 RenderTreeLODFactor 1 0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 -VertexShaderEnable 1 0 +VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 RenderDeferred 1 0 @@ -223,6 +254,12 @@ list Class3 RenderVBOEnable 1 1 // +// VRAM > 512MB +// +list VRAMGT512 +RenderCompressTextures 1 0 + +// // No Pixel Shaders available // list NoPixelShaders @@ -300,6 +337,7 @@ RenderMaxTextureIndex 1 1 list Intel RenderAnisotropic 1 0 RenderVBOEnable 1 0 +RenderFSAASamples 1 0 list GeForce2 RenderAnisotropic 1 0 diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt index 198e702459..777d54a5c3 100644 --- a/indra/newview/gpu_table.txt +++ b/indra/newview/gpu_table.txt @@ -205,6 +205,7 @@ ATI Radeon X800 .*ATI.*Radeon ?X8.* 2 1 ATI Radeon X900 .*ATI.*Radeon ?X9.* 2 1 ATI Radeon Xpress .*ATI.*Radeon Xpress.* 0 1 ATI Rage 128 .*ATI.*Rage 128.* 0 1 +ATI R300 (9700) .*R300.* 1 1 ATI R350 (9800) .*R350.* 1 1 ATI R580 (X1900) .*R580.* 3 1 ATI RC410 (Xpress 200) .*RC410.* 0 0 diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 283a28a0aa..20936c6460 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -110,22 +110,34 @@ export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}" # fi #fi -export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"${LD_LIBRARY_PATH}"' -export SL_CMD='$LL_WRAPPER bin/do-not-directly-run-secondlife-bin' -export SL_OPT="`cat etc/gridargs.dat` $@" - -# Run the program -eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || LL_RUN_ERR=runerr +export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" + +# Have to deal specially with gridargs.dat; typical contents look like: +# --channel "Second Life Developer" --settings settings_developer.xml +# Simply embedding $(<etc/gridargs.dat) into a command line treats each of +# Second, Life and Developer as separate args -- no good. We need bash to +# process quotes using eval. +# First read it without scanning, then scan that string. Break quoted words +# into a bash array. Note that if gridargs.dat is empty, or contains only +# whitespace, the resulting gridargs array will be empty -- zero entries -- +# therefore "${gridargs[@]}" entirely vanishes from the command line below, +# just as we want. +eval gridargs=("$(<etc/gridargs.dat)") + +# Run the program. +# Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the +# command line. But DO quote "$@": preserve separate args as individually +# quoted. Similar remarks about the contents of gridargs. +$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${gridargs[@]}" "$@" +LL_RUN_ERR=$? # Handle any resulting errors -if [ -n "$LL_RUN_ERR" ]; then - LL_RUN_ERR_MSG="" - if [ "$LL_RUN_ERR" = "runerr" ]; then - # generic error running the binary - echo '*** Bad shutdown. ***' - if [ "`uname -m`" = "x86_64" ]; then - echo - cat << EOFMARKER +if [ $LL_RUN_ERR -ne 0 ]; then + # generic error running the binary + echo '*** Bad shutdown ($LL_RUN_ERR). ***' + if [ "$(uname -m)" = "x86_64" ]; then + echo + cat << EOFMARKER You are running the Second Life Viewer on a x86_64 platform. The most common problems when launching the Viewer (particularly 'bin/do-not-directly-run-secondlife-bin: not found' and 'error while @@ -134,10 +146,8 @@ distribution's 32-bit compatibility packages. For example, on Ubuntu and other Debian-based Linuxes you might run: $ sudo apt-get install ia32-libs ia32-libs-gtk ia32-libs-kde ia32-libs-sdl EOFMARKER - fi fi fi - echo echo '*******************************************************' diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index ab9b5ff436..3367604753 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -169,11 +169,7 @@ bool LLAgent::isActionAllowed(const LLSD& sdname) const std::string& param = sdname.asString(); - if (param == "build") - { - retval = gAgent.canEditParcel(); - } - else if (param == "speak") + if (param == "speak") { if ( gAgent.isVoiceConnected() && LLViewerParcelMgr::getInstance()->allowAgentVoice() && @@ -3257,6 +3253,10 @@ void LLAgent::processControlRelease(LLMessageSystem *msg, void **) void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data) { gAgentQueryManager.mNumPendingQueries--; + if (gAgentQueryManager.mNumPendingQueries == 0) + { + selfStopPhase("fetch_texture_cache_entries"); + } if (!isAgentAvatarValid() || gAgentAvatarp->isDead()) { @@ -3306,13 +3306,12 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * else { // no cache of this bake. request upload. - gAgentAvatarp->requestLayerSetUpload(baked_index); + gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index),TRUE); } } } } } - llinfos << "Received cached texture response for " << num_results << " textures." << llendl; gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them"); @@ -3779,7 +3778,15 @@ void LLAgent::sendAgentSetAppearance() return; } - llinfos << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << llendl; + if (!gAgentWearables.changeInProgress()) + { + // Change is fully resolved, can close some open phases. + gAgentAvatarp->getPhases().stopPhase("process_initial_wearables_update"); + gAgentAvatarp->getPhases().stopPhase("wear_inventory_category"); + } + + gAgentAvatarp->sendAppearanceChangeMetrics(); + LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL; //dumpAvatarTEs( "sendAgentSetAppearance()" ); LLMessageSystem* msg = gMessageSystem; @@ -3826,14 +3833,14 @@ void LLAgent::sendAgentSetAppearance() // only update cache entries if we have all our baked textures if (textures_current) { - llinfos << "TAT: Sending cached texture data" << llendl; + LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sending cached texture data" << LL_ENDL; for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { BOOL generate_valid_hash = TRUE; if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLVOAvatarDefines::EBakedTextureIndex)baked_index)) { generate_valid_hash = FALSE; - llinfos << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << llendl; + LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << LL_ENDL; } const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash); diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index a8d2222c03..a4c0b056ac 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -126,6 +126,17 @@ LLAgentListener::LLAgentListener(LLAgent &agent) "[\"obj_uuid\"]: id of object to look at, use this or [\"position\"] to indicate the target\n" "[\"position\"]: region position {x, y, z} where to find closest object or avatar to look at", &LLAgentListener::lookAt); + add("getGroups", + "Send information about the agent's groups on [\"reply\"]:\n" + "[\"groups\"]: array of group information\n" + "[\"id\"]: group id\n" + "[\"name\"]: group name\n" + "[\"insignia\"]: group insignia texture id\n" + "[\"notices\"]: boolean indicating if this user accepts notices from this group\n" + "[\"display\"]: boolean indicating if this group is listed in the user's profile\n" + "[\"contrib\"]: user's land contribution to this group\n", + &LLAgentListener::getGroups, + LLSDMap("reply", LLSD())); } void LLAgentListener::requestTeleport(LLSD const & event_data) const diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 09305a5b4d..e441f21f90 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -817,7 +817,10 @@ void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index) if (wearable) { mWearableDatas[type].erase(mWearableDatas[type].begin() + index); + if (isAgentAvatarValid()) + { gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE); + } wearable->setLabelUpdated(); } } @@ -952,6 +955,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs if (isAgentAvatarValid()) { + //gAgentAvatarp->clearPhases(); // reset phase timers for outfit loading. + gAgentAvatarp->getPhases().startPhase("process_initial_wearables_update"); gAgentAvatarp->outputRezTiming("Received initial wearables update"); } @@ -1445,7 +1450,16 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it { gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); gAgentAvatarp->updateVisualParams(); - gAgentAvatarp->invalidateAll(); + + // If we have not yet declouded, we may want to use + // baked texture UUIDs sent from the first objectUpdate message + // don't overwrite these. If we have already declouded, we've saved + // these ids as the last known good textures and can invalidate without + // re-clouding. + if (!gAgentAvatarp->getIsCloud()) + { + gAgentAvatarp->invalidateAll(); + } } // Start rendering & update the server @@ -1627,10 +1641,11 @@ void LLAgentWearables::queryWearableCache() { if (isAgentAvatarValid()) { + selfStartPhase("fetch_texture_cache_entries"); gAgentAvatarp->outputRezTiming("Fetching textures from cache"); } - llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl; + LL_INFOS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL; gMessageSystem->sendReliable(gAgent.getRegion()->getHost()); gAgentQueryManager.mNumPendingQueries++; gAgentQueryManager.mWearablesCacheQueryID++; @@ -2078,6 +2093,11 @@ boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_ return mLoadedSignal.connect(cb); } +bool LLAgentWearables::changeInProgress() const +{ + return mCOFChangeInProgress; +} + void LLAgentWearables::notifyLoadingStarted() { mCOFChangeInProgress = true; diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 01cae3ffd8..5932be21c6 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -233,6 +233,7 @@ public: typedef boost::signals2::signal<void()> loaded_signal_t; boost::signals2::connection addLoadedCallback(loaded_callback_t cb); + bool changeInProgress() const; void notifyLoadingStarted(); void notifyLoadingFinished(); diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index 8cba54347e..e2417cdddb 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -89,6 +89,7 @@ LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) : { if (isAgentAvatarValid()) { + gAgentAvatarp->getPhases().startPhase("initial_wearables_fetch"); gAgentAvatarp->outputRezTiming("Initial wearables fetch started"); } } @@ -107,6 +108,7 @@ void LLInitialWearablesFetch::done() doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this)); if (isAgentAvatarValid()) { + gAgentAvatarp->getPhases().stopPhase("initial_wearables_fetch"); gAgentAvatarp->outputRezTiming("Initial wearables fetch done"); } } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 33f5373d7e..faadfb4b87 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -50,6 +50,11 @@ #include "llviewerregion.h" #include "llwearablelist.h" +std::string self_av_string() +{ + return gAgentAvatarp->avString(); +} + // RAII thingy to guarantee that a variable gets reset when the Setter // goes out of scope. More general utility would be handy - TODO: // check boost. @@ -156,6 +161,10 @@ public: { mCatID = cat_id; mAppend = append; + + LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; + + selfStartPhase("wear_inventory_category_callback"); } void fire(const LLUUID& item_id) { @@ -167,13 +176,16 @@ public: * after the last item has fired the event and dereferenced it -- if all * the events actually fire! */ + LL_DEBUGS("Avatar") << self_av_string() << " fired on copied item, id " << item_id << LL_ENDL; } protected: ~LLWearInventoryCategoryCallback() { - llinfos << "done all inventory callbacks" << llendl; + LL_INFOS("Avatar") << self_av_string() << "done all inventory callbacks" << LL_ENDL; + selfStopPhase("wear_inventory_category_callback"); + // Is the destructor called by ordinary dereference, or because the app's shutting down? // If the inventory callback manager goes away, we're shutting down, no longer want the callback. if( LLInventoryCallbackManager::is_instantiated() ) @@ -182,7 +194,7 @@ protected: } else { - llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl; + llwarns << self_av_string() << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl; } } @@ -212,11 +224,14 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit mFireCount(0), mUpdateBaseOrder(update_base_outfit_ordering) { + selfStartPhase("update_appearance_on_destroy"); } LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() { - llinfos << "done update appearance on destroy" << llendl; + LL_INFOS("Avatar") << self_av_string() << "done update appearance on destroy" << LL_ENDL; + + selfStopPhase("update_appearance_on_destroy"); if (!LLApp::isExiting()) { @@ -229,7 +244,7 @@ void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item); const std::string item_name = item ? item->getName() : "ITEM NOT FOUND"; #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL; #endif mFireCount++; } @@ -339,11 +354,16 @@ LLWearableHoldingPattern::LLWearableHoldingPattern(): } sActiveHoldingPatterns.insert(this); + selfStartPhase("holding_pattern"); } LLWearableHoldingPattern::~LLWearableHoldingPattern() { sActiveHoldingPatterns.erase(this); + if (isMostRecent()) + { + selfStopPhase("holding_pattern"); + } } bool LLWearableHoldingPattern::isMostRecent() @@ -390,9 +410,10 @@ void LLWearableHoldingPattern::checkMissingWearables() { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway why don't we actually skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } - + std::vector<S32> found_by_type(LLWearableType::WT_COUNT,0); std::vector<S32> requested_by_type(LLWearableType::WT_COUNT,0); for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it) @@ -408,7 +429,7 @@ void LLWearableHoldingPattern::checkMissingWearables() { if (requested_by_type[type] > found_by_type[type]) { - llwarns << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl; + llwarns << self_av_string() << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl; } if (found_by_type[type] > 0) continue; @@ -425,11 +446,13 @@ void LLWearableHoldingPattern::checkMissingWearables() mTypesToRecover.insert(type); mTypesToLink.insert(type); recoverMissingWearable((LLWearableType::EType)type); - llwarns << "need to replace " << type << llendl; + llwarns << self_av_string() << "need to replace " << type << llendl; } } resetTime(60.0F); + + selfStartPhase("get_missing_wearables"); if (!pollMissingWearables()) { doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollMissingWearables,this)); @@ -445,13 +468,14 @@ void LLWearableHoldingPattern::onAllComplete() if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway need to skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } // Activate all gestures in this folder if (mGestItems.count() > 0) { - llinfos << "Activating " << mGestItems.count() << " gestures" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Activating " << mGestItems.count() << " gestures" << LL_ENDL; LLGestureMgr::instance().activateGestures(mGestItems); @@ -468,13 +492,13 @@ void LLWearableHoldingPattern::onAllComplete() } // Update wearables. - llinfos << "Updating agent wearables with " << mResolved << " wearable items " << llendl; + LL_INFOS("Avatar") << self_av_string() << "Updating agent wearables with " << mResolved << " wearable items " << LL_ENDL; LLAppearanceMgr::instance().updateAgentWearables(this, false); // Update attachments to match those requested. if (isAgentAvatarValid()) { - llinfos << "Updating " << mObjItems.count() << " attachments" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.count() << " attachments" << LL_ENDL; LLAgentWearables::userUpdateAttachments(mObjItems); } @@ -492,9 +516,12 @@ void LLWearableHoldingPattern::onAllComplete() void LLWearableHoldingPattern::onFetchCompletion() { + selfStopPhase("get_wearables"); + if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } checkMissingWearables(); @@ -505,7 +532,8 @@ bool LLWearableHoldingPattern::pollFetchCompletion() { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } bool completed = isFetchCompleted(); @@ -514,14 +542,14 @@ bool LLWearableHoldingPattern::pollFetchCompletion() if (done) { - llinfos << "polling, done status: " << completed << " timed out " << timed_out - << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl; + LL_INFOS("Avatar") << self_av_string() << "polling, done status: " << completed << " timed out " << timed_out + << " elapsed " << mWaitTime.getElapsedTimeF32() << LL_ENDL; mFired = true; if (timed_out) { - llwarns << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl; + llwarns << self_av_string() << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl; } onFetchCompletion(); @@ -543,6 +571,7 @@ public: if (!mHolder->isMostRecent()) { llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? } llinfos << "Recovered item link for type " << mType << llendl; @@ -569,12 +598,12 @@ public: } else { - llwarns << "inventory item not found for recovered wearable" << llendl; + llwarns << self_av_string() << "inventory item not found for recovered wearable" << llendl; } } else { - llwarns << "inventory link not found for recovered wearable" << llendl; + llwarns << self_av_string() << "inventory link not found for recovered wearable" << llendl; } } private: @@ -596,10 +625,11 @@ public: { if (!mHolder->isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } - llinfos << "Recovered item for type " << mType << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << mType << LL_ENDL; LLViewerInventoryItem *itemp = gInventory.getItem(item_id); mWearable->setItemID(item_id); LLPointer<LLInventoryCallback> cb = new RecoveredItemLinkCB(mType,mWearable,mHolder); @@ -626,7 +656,8 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } // Try to recover by replacing missing wearable with a new one. @@ -665,7 +696,7 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable)) { // Wearable link that was never resolved; remove links to it from COF - llinfos << "removing link for unresolved item " << data.mItemID.asString() << llendl; + LL_INFOS("Avatar") << self_av_string() << "removing link for unresolved item " << data.mItemID.asString() << LL_ENDL; LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false); } } @@ -675,7 +706,8 @@ bool LLWearableHoldingPattern::pollMissingWearables() { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + // runway skip here? + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } bool timed_out = isTimedOut(); @@ -684,15 +716,17 @@ bool LLWearableHoldingPattern::pollMissingWearables() if (!done) { - llinfos << "polling missing wearables, waiting for items " << mTypesToRecover.size() + LL_INFOS("Avatar") << self_av_string() << "polling missing wearables, waiting for items " << mTypesToRecover.size() << " links " << mTypesToLink.size() << " wearables, timed out " << timed_out << " elapsed " << mWaitTime.getElapsedTimeF32() - << " done " << done << llendl; + << " done " << done << LL_ENDL; } if (done) { + selfStopPhase("get_missing_wearables"); + gAgentAvatarp->debugWearablesLoaded(); // BAP - if we don't call clearCOFLinksForMissingWearables() @@ -722,14 +756,14 @@ void LLWearableHoldingPattern::handleLateArrivals() } if (!isMostRecent()) { - llwarns << "Late arrivals not handled - outfit change no longer valid" << llendl; + llwarns << self_av_string() << "Late arrivals not handled - outfit change no longer valid" << llendl; } if (!mIsAllComplete) { - llwarns << "Late arrivals not handled - in middle of missing wearables processing" << llendl; + llwarns << self_av_string() << "Late arrivals not handled - in middle of missing wearables processing" << llendl; } - llinfos << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << llendl; + LL_INFOS("Avatar") << self_av_string() << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << LL_ENDL; // Update mFoundList using late-arriving wearables. std::set<LLWearableType::EType> replaced_types; @@ -805,19 +839,19 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) { if (!isMostRecent()) { - llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; + llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; } mResolved += 1; // just counting callbacks, not successes. - llinfos << "resolved " << mResolved << "/" << getFoundList().size() << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "resolved " << mResolved << "/" << getFoundList().size() << LL_ENDL; if (!wearable) { - llwarns << "no wearable found" << llendl; + llwarns << self_av_string() << "no wearable found" << llendl; } if (mFired) { - llwarns << "called after holder fired" << llendl; + llwarns << self_av_string() << "called after holder fired" << llendl; if (wearable) { mLateArrivals.insert(wearable); @@ -843,7 +877,7 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) // Failing this means inventory or asset server are corrupted in a way we don't handle. if ((data.mWearableType >= LLWearableType::WT_COUNT) || (wearable->getType() != data.mWearableType)) { - llwarns << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl; + llwarns << self_av_string() << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl; break; } @@ -1391,8 +1425,8 @@ void LLAppearanceMgr::filterWearableItems( // Create links to all listed items. void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, - LLInventoryModel::item_array_t& items, - LLPointer<LLInventoryCallback> cb) + LLInventoryModel::item_array_t& items, + LLPointer<LLInventoryCallback> cb) { for (S32 i=0; i<items.count(); i++) { @@ -1408,7 +1442,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND"; #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << LL_ENDL; #endif } } @@ -1416,7 +1450,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) { LLViewerInventoryCategory *pcat = gInventory.getCategory(category); - llinfos << "starting, cat " << (pcat ? pcat->getName() : "[UNKNOWN]") << llendl; + LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL; const LLUUID cof = getCOF(); @@ -1478,26 +1512,26 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) gInventory.notifyObservers(); // Create links to new COF contents. - llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "creating LLUpdateAppearanceOnDestroy" << LL_ENDL; LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(!append); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking body items" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking body items" << LL_ENDL; #endif linkAll(cof, body_items, link_waiter); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking wear items" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking wear items" << LL_ENDL; #endif linkAll(cof, wear_items, link_waiter); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking obj items" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking obj items" << LL_ENDL; #endif linkAll(cof, obj_items, link_waiter); #ifndef LL_RELEASE_FOR_DOWNLOAD - llinfos << "Linking gesture items" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Linking gesture items" << LL_ENDL; #endif linkAll(cof, gest_items, link_waiter); @@ -1506,7 +1540,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) { createBaseOutfitLink(category, link_waiter); } - llinfos << "waiting for LLUpdateAppearanceOnDestroy" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; } void LLAppearanceMgr::updatePanelOutfitName(const std::string& name) @@ -1663,7 +1697,7 @@ void LLAppearanceMgr::enforceItemRestrictions() ++it) { LLViewerInventoryItem *item = *it; - llinfos << "purging duplicate or excess item " << item->getName() << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "purging duplicate or excess item " << item->getName() << LL_ENDL; gInventory.purgeObject(item->getUUID()); } gInventory.notifyObservers(); @@ -1678,9 +1712,11 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) return; } + LLVOAvatar::ScopedPhaseSetter(gAgentAvatarp,"update_appearance_from_cof"); + BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF); - llinfos << "starting" << llendl; + LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; //checking integrity of the COF in terms of ordering of wearables, //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) @@ -1772,12 +1808,14 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) } } + selfStartPhase("get_wearables"); + for (LLWearableHoldingPattern::found_list_t::iterator it = holder->getFoundList().begin(); it != holder->getFoundList().end(); ++it) { LLFoundData& found = *it; - lldebugs << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl; + lldebugs << self_av_string() << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl; // Fetch the wearables about to be worn. LLWearableList::instance().getAsset(found.mAssetID, @@ -1849,11 +1887,15 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool { if(!category) return; + selfClearPhases(); + selfStartPhase("wear_inventory_category"); + gAgentWearables.notifyLoadingStarted(); - llinfos << "wearInventoryCategory( " << category->getName() - << " )" << llendl; + LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategory( " << category->getName() + << " )" << LL_ENDL; + selfStartPhase("wear_inventory_category_fetch"); callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal, &LLAppearanceMgr::instance(), category->getUUID(), copy, append)); @@ -1861,7 +1903,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append) { - llinfos << "starting" << llendl; + LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; + + selfStopPhase("wear_inventory_category_fetch"); // We now have an outfit ready to be copied to agent inventory. Do // it, and wear that outfit normally. @@ -1944,8 +1988,8 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego // wearables being dirty. if(!category) return; - llinfos << "wearInventoryCategoryOnAvatar( " << category->getName() - << " )" << llendl; + LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName() + << "'" << LL_ENDL; if (gAgentCamera.cameraCustomizeAvatar()) { @@ -1958,7 +2002,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego void LLAppearanceMgr::wearOutfitByName(const std::string& name) { - llinfos << "Wearing category " << name << llendl; + LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL; //inc_busy_count(); LLInventoryModel::cat_array_t cat_array; @@ -2281,7 +2325,7 @@ const std::string OTHER_GESTURES_FOLDER = "Other Gestures"; void LLAppearanceMgr::copyLibraryGestures() { - llinfos << "Copying library gestures" << llendl; + LL_INFOS("Avatar") << self_av_string() << "Copying library gestures" << LL_ENDL; // Copy gestures LLUUID lib_gesture_cat_id = @@ -2337,11 +2381,11 @@ void LLAppearanceMgr::copyLibraryGestures() LLUUID cat_id = findDescendentCategoryIDByName(lib_gesture_cat_id,folder_name); if (cat_id.isNull()) { - llwarns << "failed to find gesture folder for " << folder_name << llendl; + llwarns << self_av_string() << "failed to find gesture folder for " << folder_name << llendl; } else { - llinfos << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << LL_ENDL; callAfterCategoryFetch(cat_id, boost::bind(&LLAppearanceMgr::shallowCopyCategory, &LLAppearanceMgr::instance(), @@ -2355,7 +2399,7 @@ void LLAppearanceMgr::autopopulateOutfits() // If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account) // then auto-populate outfits from the library into the My Outfits folder. - llinfos << "avatar fully visible" << llendl; + LL_INFOS("Avatar") << self_av_string() << "avatar fully visible" << LL_ENDL; static bool check_populate_my_outfits = true; if (check_populate_my_outfits && @@ -2731,7 +2775,7 @@ void LLAppearanceMgr::dumpCat(const LLUUID& cat_id, const std::string& msg) } void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items, - const std::string& msg) + const std::string& msg) { for (S32 i=0; i<items.count(); i++) { @@ -2742,9 +2786,8 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items, { asset_id = linked_item->getAssetUUID(); } - llinfos << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << llendl; + LL_DEBUGS("Avatar") << self_av_string() << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << LL_ENDL; } - llinfos << llendl; } LLAppearanceMgr::LLAppearanceMgr(): diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 49fbdbf1df..d033252029 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -93,6 +93,7 @@ #include "llsecondlifeurls.h" #include "llupdaterservice.h" #include "llcallfloater.h" +#include "llfloatertexturefetchdebugger.h" // Linden library includes #include "llavatarnamecache.h" @@ -111,6 +112,8 @@ #include "llnotifications.h" #include "llnotificationsutil.h" +#include "llleap.h" + // Third party library includes #include <boost/bind.hpp> #include <boost/foreach.hpp> @@ -124,7 +127,6 @@ #endif #include "llapr.h" -#include "apr_dso.h" #include <boost/lexical_cast.hpp> #include "llviewerkeyboard.h" @@ -161,6 +163,7 @@ #include "llcontainerview.h" #include "lltooltip.h" +#include "llsdutil.h" #include "llsdserialize.h" #include "llworld.h" @@ -528,6 +531,7 @@ static void settings_to_globals() LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile"); LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); + LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor"); LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); @@ -545,7 +549,7 @@ static void settings_to_globals() gAgentPilot.setNumRuns(gSavedSettings.getS32("StatsNumRuns")); gAgentPilot.setQuitAfterRuns(gSavedSettings.getBOOL("StatsQuitAfterRuns")); gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle")); - + gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc"); gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale"); @@ -560,7 +564,6 @@ static void settings_modify() LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession; gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); - gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); } class LLFastTimerLogThread : public LLThread @@ -622,6 +625,7 @@ LLAppViewer::LLAppViewer() : mPurgeOnExit(false), mSecondInstance(false), mSavedFinalSnapshot(false), + mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. mForceGraphicsDetail(false), mQuitRequested(false), mLogoutRequestSent(false), @@ -731,12 +735,12 @@ bool LLAppViewer::init() { // Viewer metrics initialization - static LLCachedControl<bool> metrics_submode(gSavedSettings, - "QAModeMetrics", - false, - "Enables QA features (logging, faster cycling) for metrics collector"); + //static LLCachedControl<bool> metrics_submode(gSavedSettings, + // "QAModeMetrics", + // false, + // "Enables QA features (logging, faster cycling) for metrics collector"); - if (metrics_submode) + if (gSavedSettings.getBOOL("QAModeMetrics")) { app_metrics_qa_mode = true; app_metrics_interval = METRICS_INTERVAL_QA; @@ -1014,6 +1018,15 @@ bool LLAppViewer::init() } } +#if LL_WINDOWS + if (gGLManager.mIsIntel && + LLFeatureManager::getInstance()->getGPUClass() > 0 && + gGLManager.mGLVersion <= 3.f) + { + LLNotificationsUtil::add("IntelOldDriver"); + } +#endif + // save the graphics card gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString(); @@ -1038,11 +1051,38 @@ bool LLAppViewer::init() gGLActive = FALSE; + + // Iterate over --leap command-line options. But this is a bit tricky: if + // there's only one, it won't be an array at all. + LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand")); + LL_DEBUGS("InitInfo") << "LeapCommand: " << LeapCommand << LL_ENDL; + if (LeapCommand.isDefined() && ! LeapCommand.isArray()) + { + // If LeapCommand is actually a scalar value, make an array of it. + // Have to do it in two steps because LeapCommand.append(LeapCommand) + // trashes content! :-P + LLSD item(LeapCommand); + LeapCommand.append(item); + } + BOOST_FOREACH(const std::string& leap, llsd::inArray(LeapCommand)) + { + LL_INFOS("InitInfo") << "processing --leap \"" << leap << '"' << LL_ENDL; + // We don't have any better description of this plugin than the + // user-specified command line. Passing "" causes LLLeap to derive a + // description from the command line itself. + // Suppress LLLeap::Error exception: trust LLLeap's own logging. We + // don't consider any one --leap command mission-critical, so if one + // fails, log it, shrug and carry on. + LLLeap::create("", leap, false); // exception=false + } + if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0) { - loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort")); + LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: " + << "lleventhost no longer supported as a dynamic library" + << LL_ENDL; } - + LLViewerMedia::initClass(); LL_INFOS("InitInfo") << "Viewer media initialized." << LL_ENDL ; @@ -1219,7 +1259,7 @@ bool LLAppViewer::mainLoop() if(mem_leak_instance) { mem_leak_instance->idle() ; - } + } // canonical per-frame event mainloop.post(newFrame); @@ -1340,13 +1380,11 @@ bool LLAppViewer::mainLoop() ms_sleep(500); } - static const F64 FRAME_SLOW_THRESHOLD = 0.5; //2 frames per seconds const F64 max_idle_time = llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second idleTimer.reset(); - bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ; S32 total_work_pending = 0; S32 total_io_pending = 0; - while(!is_slow)//do not unpause threads if the frame rates are very low. + while(1) { S32 work_pending = 0; S32 io_pending = 0; @@ -1406,6 +1444,17 @@ bool LLAppViewer::mainLoop() LLLFSThread::sLocal->pause(); } + //texture fetching debugger + if(LLTextureFetchDebugger::isEnabled()) + { + LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = + LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); + if(tex_fetch_debugger_instance) + { + tex_fetch_debugger_instance->idle() ; + } + } + if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) { @@ -1487,6 +1536,9 @@ void LLAppViewer::flushVFSIO() bool LLAppViewer::cleanup() { + //ditch LLVOAvatarSelf instance + gAgentAvatarp = NULL; + // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); @@ -1508,21 +1560,27 @@ bool LLAppViewer::cleanup() if (! isError()) { std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); - logdir += gDirUtilp->getDirDelimiter(); gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); } - // *TODO - generalize this and move DSO wrangling to a helper class -brad - std::set<struct apr_dso_handle_t *>::const_iterator i; - for(i = mPlugins.begin(); i != mPlugins.end(); ++i) { - int (*ll_plugin_stop_func)(void) = NULL; - apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop"); - ll_plugin_stop_func(); - - rv = apr_dso_unload(*i); - } - mPlugins.clear(); + // Kill off LLLeap objects. We can find them all because LLLeap is derived + // from LLInstanceTracker. But collect instances first: LLInstanceTracker + // specifically forbids adding/deleting instances while iterating. + std::vector<LLLeap*> leaps; + leaps.reserve(LLLeap::instanceCount()); + for (LLLeap::instance_iter li(LLLeap::beginInstances()), lend(LLLeap::endInstances()); + li != lend; ++li) + { + leaps.push_back(&*li); + } + // Okay, now trash them all. We don't have to NULL or erase the entry + // in 'leaps' because the whole vector is going away momentarily. + BOOST_FOREACH(LLLeap* leap, leaps) + { + delete leap; + } + } // destroy 'leaps' //flag all elements as needing to be destroyed immediately // to ensure shutdown order @@ -1739,6 +1797,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); @@ -1757,8 +1822,7 @@ bool LLAppViewer::cleanup() if (mPurgeOnExit) { llinfos << "Purging all cache files on exit" << llendflush; - std::string mask = gDirUtilp->getDirDelimiter() + "*.*"; - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask); + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); } removeMarkerFile(); // Any crashes from here on we'll just have to ignore @@ -1948,7 +2012,7 @@ bool LLAppViewer::initThreads() static const bool enable_threads = true; #endif - LLImage::initClass(); + LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); LLVFSThread::initClass(enable_threads && false); LLLFSThread::initClass(enable_threads && false); @@ -2992,8 +3056,7 @@ void LLAppViewer::cleanupSavedSettings() void LLAppViewer::removeCacheFiles(const std::string& file_mask) { - std::string mask = gDirUtilp->getDirDelimiter() + file_mask; - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask); + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask); } void LLAppViewer::writeSystemInfo() @@ -3852,8 +3915,7 @@ void LLAppViewer::purgeCache() LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL; LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); LLVOCache::getInstance()->removeCache(LL_PATH_CACHE); - std::string mask = "*.*"; - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask); + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*.*"); } std::string LLAppViewer::getSecondLifeTitle() const @@ -4198,6 +4260,7 @@ void LLAppViewer::idle() // The 5-second interval is nice for this purpose. If the object debug // bit moves or is disabled, please give this a suitable home. LLViewerAssetStatsFF::record_fps_main(gFPSClamped); + LLViewerAssetStatsFF::record_avatar_stats(); } } @@ -4245,7 +4308,8 @@ void LLAppViewer::idle() static LLTimer report_interval; // *TODO: Add configuration controls for this - if (report_interval.getElapsedTimeF32() >= app_metrics_interval) + F32 seconds = report_interval.getElapsedTimeF32(); + if (seconds >= app_metrics_interval) { metricsSend(! gDisconnected); report_interval.reset(); @@ -4953,87 +5017,10 @@ void LLAppViewer::handleLoginComplete() mOnLoginCompleted(); writeDebugInfo(); -} - -// *TODO - generalize this and move DSO wrangling to a helper class -brad -void LLAppViewer::loadEventHostModule(S32 listen_port) -{ - std::string dso_name = -#if LL_WINDOWS - "lleventhost.dll"; -#elif LL_DARWIN - "liblleventhost.dylib"; -#else - "liblleventhost.so"; -#endif - - std::string dso_path = gDirUtilp->findFile(dso_name, - gDirUtilp->getAppRODataDir(), - gDirUtilp->getExecutableDir()); - - if(dso_path == "") - { - llerrs << "QAModeEventHost requested but module \"" << dso_name << "\" not found!" << llendl; - return; - } - - LL_INFOS("eventhost") << "Found lleventhost at '" << dso_path << "'" << LL_ENDL; -#if ! defined(LL_WINDOWS) - { - std::string outfile("/tmp/lleventhost.file.out"); - std::string command("file '" + dso_path + "' > '" + outfile + "' 2>&1"); - int rc = system(command.c_str()); - if (rc != 0) - { - LL_WARNS("eventhost") << command << " ==> " << rc << ':' << LL_ENDL; - } - else - { - LL_INFOS("eventhost") << command << ':' << LL_ENDL; - } - { - std::ifstream reader(outfile.c_str()); - std::string line; - while (std::getline(reader, line)) - { - size_t len = line.length(); - if (len && line[len-1] == '\n') - line.erase(len-1); - LL_INFOS("eventhost") << line << LL_ENDL; - } - } - remove(outfile.c_str()); - } -#endif // LL_WINDOWS - - apr_dso_handle_t * eventhost_dso_handle = NULL; - apr_pool_t * eventhost_dso_memory_pool = NULL; - - //attempt to load the shared library - apr_pool_create(&eventhost_dso_memory_pool, NULL); - apr_status_t rv = apr_dso_load(&eventhost_dso_handle, - dso_path.c_str(), - eventhost_dso_memory_pool); - llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle)); - llassert_always(eventhost_dso_handle != NULL); - - int (*ll_plugin_start_func)(LLSD const &) = NULL; - rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start"); - - llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle)); - llassert_always(ll_plugin_start_func != NULL); - - LLSD args; - args["listen_port"] = listen_port; - - int status = ll_plugin_start_func(args); - - if(status != 0) - { - llerrs << "problem loading eventhost plugin, status: " << status << llendl; - } - mPlugins.insert(eventhost_dso_handle); + // we logged in successfully, so save settings on logout + llinfos << "Login successful, per account settings will be saved on log out." << llendl; + mSavePerAccountSettings=true; } void LLAppViewer::launchUpdater() diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 71a7868191..ae3c795d1e 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -41,8 +41,6 @@ class LLTextureFetch; class LLWatchdogTimeout; class LLUpdaterService; -struct apr_dso_handle_t; - class LLAppViewer : public LLApp { public: @@ -220,8 +218,6 @@ private: void sendLogoutRequest(); void disconnectViewer(); - - void loadEventHostModule(S32 listen_port); // *FIX: the app viewer class should be some sort of singleton, no? // Perhaps its child class is the singleton and this should be an abstract base. @@ -251,6 +247,7 @@ private: bool mPurgeOnExit; bool mSavedFinalSnapshot; + bool mSavePerAccountSettings; // only save per account settings if login succeeded bool mForceGraphicsDetail; @@ -270,8 +267,6 @@ private: LLAllocator mAlloc; - std::set<struct apr_dso_handle_t*> mPlugins; - LLFrameTimer mMemCheckTimer; boost::scoped_ptr<LLUpdaterService> mUpdater; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 647ace7ee3..bad60a9757 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -26,11 +26,16 @@ #include "llviewerprecompiledheaders.h" +#ifdef INCLUDE_VLD +#include "vld.h" +#endif + #include "llappviewerwin32.h" #include "llmemtype.h" -#include "llwindowwin32.cpp" // *FIX: for setting gIconResource. +#include "llwindowwin32.h" // *FIX: for setting gIconResource. +#include "llgl.h" #include "res/resource.h" // *FIX: for setting gIconResource. #include <fcntl.h> //_O_APPEND @@ -104,6 +109,14 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow) { +#ifdef INCLUDE_VLD + // only works for debug builds (hard coded into vld.h) + #ifdef _DEBUG + // start with Visual Leak Detector turned off + VLDGlobalDisable(); + #endif // _DEBUG +#endif // INCLUDE_VLD + LLMemType mt1(LLMemType::MTYPE_STARTUP); const S32 MAX_HEAPS = 255; diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp index 7e50098a17..f943759bb8 100644 --- a/indra/newview/llassetuploadqueue.cpp +++ b/indra/newview/llassetuploadqueue.cpp @@ -123,7 +123,9 @@ public: for(LLSD::array_const_iterator line = compile_errors.beginArray(); line < compile_errors.endArray(); line++) { - mSupplier->log(line->asString()); + std::string str = line->asString(); + str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); + mSupplier->log(str); llinfos << content["errors"] << llendl; } } diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 9a7cdcfa21..fdd4565e50 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -594,7 +594,7 @@ namespace action_give_inventory } S32 count = LLShareInfo::instance().mAvatarNames.size(); - bool shared = false; + bool shared = count && !inventory_selected_uuids.empty(); // iterate through avatars for(S32 i = 0; i < count; ++i) @@ -616,8 +616,10 @@ namespace action_give_inventory LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); if (inv_cat) { - LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id); - shared = true; + if (!LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id, "ItemsShared")) + { + shared = false; + } break; } LLViewerInventoryItem* inv_item = gInventory.getItem(*it); @@ -632,8 +634,10 @@ namespace action_give_inventory } else { - LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id); - shared = true; + if (!LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id)) + { + shared = false; + } } } if (noncopy_items.beginArray() != noncopy_items.endArray()) @@ -643,8 +647,10 @@ namespace action_give_inventory LLSD payload; payload["agent_id"] = avatar_uuid; payload["items"] = noncopy_items; + payload["success_notification"] = "ItemsShared"; LLNotificationsUtil::add("CannotCopyWarning", substitutions, payload, &LLGiveInventory::handleCopyProtectedItem); + shared = false; break; } } @@ -738,6 +744,11 @@ void LLAvatarActions::shareWithAvatars() LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE); + if (!picker) + { + return; + } + picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable)); picker->openFriendsTab(); LLNotificationsUtil::add("ShareNotification"); diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index b1cd83a1fb..706bc42ea0 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -33,6 +33,7 @@ #include "llagentpicksinfo.h" #include "lldateutil.h" #include "llviewergenericmessage.h" +#include "llstartup.h" // Linden library includes #include "llavatarconstants.h" // AVATAR_TRANSACTED, etc. @@ -113,6 +114,14 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EA void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id) { + // this is the startup state when send_complete_agent_movement() message is sent. + // Before this, the AvatarPropertiesRequest message + // won't work so don't bother trying + if (LLStartUp::getStartupState() <= STATE_AGENT_SEND) + { + return; + } + if (isPendingRequest(avatar_id, APT_PROPERTIES)) { // waiting for a response, don't re-request diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index e3217668c5..f2375bfa4f 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -188,7 +188,7 @@ void LLCallFloater::draw() // Need to resort the participant list if it's in sort by recent speaker order. if (mParticipants) - mParticipants->updateRecentSpeakersOrder(); + mParticipants->update(); LLFloater::draw(); } @@ -333,6 +333,7 @@ void LLCallFloater::refreshParticipantList() if (!non_avatar_caller) { + llassert(mParticipants == NULL); // check for possible memory leak mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false); mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1)); const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index aabab0ccb9..a661808d1f 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -1113,8 +1113,8 @@ LLChicletPanel::~LLChicletPanel() } } -void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){ - +void LLChicletPanel::onMessageCountChanged(const LLSD& data) +{ LLUUID session_id = data["session_id"].asUUID(); S32 unread = data["participant_unread"].asInteger(); @@ -1139,7 +1139,7 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){ } } -void object_chiclet_callback(const LLSD& data) +void LLChicletPanel::objectChicletCallback(const LLSD& data) { LLUUID notification_id = data["notification_id"]; bool new_message = data["new_message"]; @@ -1163,10 +1163,10 @@ void object_chiclet_callback(const LLSD& data) BOOL LLChicletPanel::postBuild() { LLPanel::postBuild(); - LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1)); - LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1)); - LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(object_chiclet_callback, _1)); - LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(object_chiclet_callback, _1)); + LLIMModel::instance().addNewMsgCallback(boost::bind(&LLChicletPanel::onMessageCountChanged, this, _1)); + LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLChicletPanel::onMessageCountChanged, this, _1)); + LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(&LLChicletPanel::objectChicletCallback, this, _1)); + LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(&LLChicletPanel::objectChicletCallback, this, _1)); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1)); LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1)); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 1f1069dcb4..19683492c2 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -1158,6 +1158,10 @@ protected: */ void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param); + void onMessageCountChanged(const LLSD& data); + + void objectChicletCallback(const LLSD& data); + typedef std::vector<LLChiclet*> chiclet_list_t; /** diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 65c61c4a8b..17d403bbe1 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -342,6 +342,15 @@ bool LLCommandLineParser::parseCommandLine(int argc, char **argv) return parseAndStoreResults(clp); } +// TODO: +// - Break out this funky parsing logic into separate method +// - Unit-test it with tests like LLStringUtil::getTokens() (the command-line +// overload that supports quoted tokens) +// - Unless this logic offers significant semantic benefits, replace it with +// LLStringUtil::getTokens(). This would fix a known bug: you cannot --set a +// string-valued variable to the empty string, because empty strings are +// eliminated below. + bool LLCommandLineParser::parseCommandLineString(const std::string& str) { // Split the string content into tokens diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index a42677845e..4f5f9e22b6 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -100,6 +100,7 @@ BOOL LLFloaterScriptQueue::postBuild() { childSetAction("close",onCloseBtn,this); getChildView("close")->setEnabled(FALSE); + setVisible(true); return TRUE; } @@ -158,7 +159,6 @@ void LLFloaterScriptQueue::addObject(const LLUUID& id) BOOL LLFloaterScriptQueue::start() { - //llinfos << "LLFloaterCompileQueue::start()" << llendl; std::string buffer; LLSelectMgr *mgr = LLSelectMgr::getInstance(); @@ -178,7 +178,7 @@ BOOL LLFloaterScriptQueue::start() args["[COUNT]"] = llformat ("%d", mObjectIDs.count()); buffer = getString ("Starting", args); - getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer); + getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM); return nextObject(); } @@ -211,7 +211,7 @@ BOOL LLFloaterScriptQueue::nextObject() if(isDone() && !mDone) { mDone = true; - getChild<LLScrollListCtrl>("queue output")->setCommentText(getString("Done")); + getChild<LLScrollListCtrl>("queue output")->addSimpleElement(getString("Done"), ADD_BOTTOM); getChildView("close")->setEnabled(TRUE); } return successful_start; @@ -277,7 +277,7 @@ public: return; } - queue->getChild<LLScrollListCtrl>("queue output")->setCommentText(message); + queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM); } private: @@ -464,7 +464,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, } if(queue && (buffer.size() > 0)) { - queue->getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer); + queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM); } delete data; } @@ -637,7 +637,7 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); std::string buffer; buffer = getString("Resetting") + (": ") + item->getName(); - getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer); + getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_ScriptReset); msg->nextBlockFast(_PREHASH_AgentData); @@ -690,7 +690,7 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj, LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output"); std::string buffer; buffer = getString("Running") + (": ") + item->getName(); - list->setCommentText(buffer); + list->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_SetScriptRunning); @@ -745,7 +745,7 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj, LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output"); std::string buffer; buffer = getString("NotRunning") + (": ") +item->getName(); - list->setCommentText(buffer); + list->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_SetScriptRunning); diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp index 7d3170cb76..29b1d23d7d 100644 --- a/indra/newview/lldebugview.cpp +++ b/indra/newview/lldebugview.cpp @@ -68,8 +68,6 @@ LLDebugView::~LLDebugView() gDebugView = NULL; gTextureView = NULL; gSceneView = NULL; - gTextureSizeView = NULL; - gTextureCategoryView = NULL; } void LLDebugView::init() @@ -117,35 +115,11 @@ void LLDebugView::init() LLTextureView::Params tvp; tvp.name("gTextureView"); tvp.rect(r); - tvp.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); + tvp.follows.flags(FOLLOWS_TOP|FOLLOWS_LEFT); tvp.visible(false); gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp); addChild(gTextureView); //gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE); - - - if(gAuditTexture) - { - r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100); - LLTextureSizeView::Params tsv ; - tsv.name("gTextureSizeView"); - tsv.rect(r); - tsv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); - tsv.visible(false); - gTextureSizeView = LLUICtrlFactory::create<LLTextureSizeView>(tsv); - addChild(gTextureSizeView); - gTextureSizeView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_SIZE) ; - - r.set(150, rect.getHeight() - 50, 900 + LLViewerTexture::getTotalNumOfCategories() * 30, 100); - LLTextureSizeView::Params tcv ; - tcv.name("gTextureCategoryView"); - tcv.rect(r); - tcv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); - tcv.visible(false); - gTextureCategoryView = LLUICtrlFactory::create<LLTextureSizeView>(tcv); - gTextureCategoryView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_CATEGORY); - addChild(gTextureCategoryView); - } } void LLDebugView::draw() diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 5a2981e749..64774d06df 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -133,6 +133,7 @@ public: PASS_ALPHA, PASS_ALPHA_MASK, PASS_FULLBRIGHT_ALPHA_MASK, + PASS_ALPHA_INVISIBLE, NUM_RENDER_TYPES, }; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index ddb7d3ceeb..5b62dbc560 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -337,6 +337,7 @@ void LLDrawPoolAlpha::render(S32 pass) pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); if(shaders) { diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index b002c11af5..0103373fd2 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1138,6 +1138,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } + llassert(LLPipeline::sImpostorRender || !avatarp->isVisuallyMuted()); + /*if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview, 3=morph view { gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f)); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index b58efe62ab..6f71e6ebc8 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1341,8 +1341,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI // immediately assign bump to a global smart pointer in case some local smart pointer // accidentally releases it. LLPointer<LLViewerTexture> bump = LLViewerTextureManager::getLocalTexture( TRUE ); - - + if (!LLPipeline::sRenderDeferred) { LLFastTimer t(FTM_BUMP_SOURCE_CREATE); @@ -1351,6 +1350,10 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } else { //convert to normal map + + //disable compression on normal maps to prevent errors below + bump->getGLTexture()->setAllowCompression(false); + { LLFastTimer t(FTM_BUMP_SOURCE_CREATE); bump->setExplicitFormat(GL_RGBA8, GL_ALPHA); diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 8f47d3c5e5..64eb11fc9b 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -139,7 +139,7 @@ void LLDriverParamInfo::toStream(std::ostream &out) } else { - llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp << " for driver parameter " << getID() << llendl; + llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp.get() << " for driver parameter " << getID() << llendl; } out << std::endl; } diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 5d6081a35c..bf8338e5f2 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -125,8 +125,16 @@ BOOL LLViewerDynamicTexture::render() //----------------------------------------------------------------------------- void LLViewerDynamicTexture::preRender(BOOL clear_depth) { - { - // force rendering to on-screen portion of frame buffer + //only images up to 512x512 are supported + llassert(mFullHeight <= 512); + llassert(mFullWidth <= 512); + + if (gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete()) + { //using offscreen render target, just use the bottom left corner + mOrigin.set(0, 0); + } + else + { // force rendering to on-screen portion of frame buffer LLCoordScreen window_pos; gViewerWindow->getWindow()->getPosition( &window_pos ); mOrigin.set(0, gViewerWindow->getWindowHeightRaw() - mFullHeight); // top left corner @@ -140,9 +148,9 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) mOrigin.mY += window_pos.mY; mOrigin.mY = llmax(mOrigin.mY, 0) ; } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); // Set up camera LLViewerCamera* camera = LLViewerCamera::getInstance(); mCamera.setOrigin(*camera); @@ -208,6 +216,15 @@ BOOL LLViewerDynamicTexture::updateAllInstances() return TRUE; } +#if 0 //THIS CAUSES MAINT-1092 + bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete(); + + if (use_fbo) + { + gPipeline.mWaterDis.bindTarget(); + } +#endif + LLGLSLShader::bindNoShader(); LLVertexBuffer::unbind(); @@ -241,6 +258,13 @@ BOOL LLViewerDynamicTexture::updateAllInstances() } } +#if 0 + if (use_fbo) + { + gPipeline.mWaterDis.flush(); + } +#endif + return ret; } diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 2abfbf37ca..935dcb74b0 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -55,7 +55,7 @@ public: else { width = mEditor.getDocumentView()->getRect().getWidth() - mEditor.getHPad(); - height = llceil(mStyle->getFont()->getLineHeight()); + height = mStyle->getFont()->getLineHeight(); } return true; } diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp index ed1d7e860a..9480e54809 100644 --- a/indra/newview/llexternaleditor.cpp +++ b/indra/newview/llexternaleditor.cpp @@ -29,6 +29,9 @@ #include "lltrans.h" #include "llui.h" +#include "llprocess.h" +#include "llsdutil.h" +#include <boost/foreach.hpp> // static const std::string LLExternalEditor::sFilenameMarker = "%s"; @@ -45,19 +48,8 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env return EC_NOT_SPECIFIED; } - // Add the filename marker if missing. - if (cmd.find(sFilenameMarker) == std::string::npos) - { - cmd += " \"" + sFilenameMarker + "\""; - llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl; - } - string_vec_t tokens; - if (tokenize(tokens, cmd) < 2) // 2 = bin + at least one arg (%s) - { - llwarns << "Error parsing editor command" << llendl; - return EC_PARSE_ERROR; - } + tokenize(tokens, cmd); // Check executable for existence. std::string bin_path = tokens[0]; @@ -68,51 +60,48 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env } // Save command. - mProcess.setExecutable(bin_path); - mArgs.clear(); + mProcessParams = LLProcess::Params(); + mProcessParams.executable = bin_path; for (size_t i = 1; i < tokens.size(); ++i) { - if (i > 1) mArgs += " "; - mArgs += "\"" + tokens[i] + "\""; + mProcessParams.args.add(tokens[i]); } - llinfos << "Setting command [" << bin_path << " " << mArgs << "]" << llendl; + + // Add the filename marker if missing. + if (cmd.find(sFilenameMarker) == std::string::npos) + { + mProcessParams.args.add(sFilenameMarker); + llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl; + } + + llinfos << "Setting command [" << mProcessParams << "]" << llendl; return EC_SUCCESS; } LLExternalEditor::EErrorCode LLExternalEditor::run(const std::string& file_path) { - std::string args = mArgs; - if (mProcess.getExecutable().empty() || args.empty()) + if (std::string(mProcessParams.executable).empty() || mProcessParams.args.empty()) { llwarns << "Editor command not set" << llendl; return EC_NOT_SPECIFIED; } - // Substitute the filename marker in the command with the actual passed file name. - LLStringUtil::replaceString(args, sFilenameMarker, file_path); - - // Split command into separate tokens. - string_vec_t tokens; - tokenize(tokens, args); + // Copy params block so we can replace sFilenameMarker + LLProcess::Params params; + params.executable = mProcessParams.executable; - // Set process arguments taken from the command. - mProcess.clearArguments(); - for (string_vec_t::const_iterator arg_it = tokens.begin(); arg_it != tokens.end(); ++arg_it) - { - mProcess.addArgument(*arg_it); - } - - // Run the editor. - llinfos << "Running editor command [" << mProcess.getExecutable() + " " + args << "]" << llendl; - int result = mProcess.launch(); - if (result == 0) + // Substitute the filename marker in the command with the actual passed file name. + BOOST_FOREACH(const std::string& arg, mProcessParams.args) { - // Prevent killing the process in destructor (will add it to the zombies list). - mProcess.orphan(); + std::string fixed(arg); + LLStringUtil::replaceString(fixed, sFilenameMarker, file_path); + params.args.add(fixed); } - return result == 0 ? EC_SUCCESS : EC_FAILED_TO_RUN; + // Run the editor. Prevent killing the process in destructor. + params.autokill = false; + return LLProcess::create(params) ? EC_SUCCESS : EC_FAILED_TO_RUN; } // static @@ -130,6 +119,12 @@ std::string LLExternalEditor::getErrorMessage(EErrorCode code) return LLTrans::getString("Unknown"); } +// TODO: +// - Unit-test this with tests like LLStringUtil::getTokens() (the +// command-line overload that supports quoted tokens) +// - Unless there are significant semantic differences, eliminate this method +// and use LLStringUtil::getTokens() instead. + // static size_t LLExternalEditor::tokenize(string_vec_t& tokens, const std::string& str) { diff --git a/indra/newview/llexternaleditor.h b/indra/newview/llexternaleditor.h index ef5db56c6e..fd2c25020c 100644 --- a/indra/newview/llexternaleditor.h +++ b/indra/newview/llexternaleditor.h @@ -27,7 +27,7 @@ #ifndef LL_LLEXTERNALEDITOR_H #define LL_LLEXTERNALEDITOR_H -#include <llprocesslauncher.h> +#include "llprocess.h" /** * Usage: @@ -97,9 +97,7 @@ private: */ static const std::string sSetting; - - std::string mArgs; - LLProcessLauncher mProcess; + LLProcess::Params mProcessParams; }; #endif // LL_LLEXTERNALEDITOR_H diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index cd33a19a2a..4108d69e82 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1742,14 +1742,22 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a texIdx; - F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0); + U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + + F32 val = 0.f; + U8* vp = (U8*) &val; + vp[0] = index; + vp[1] = 0; + vp[2] = 0; + vp[3] = 0; + llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); LLVector4Logical mask; mask.clear(); mask.setElement<3>(); - texIdx.set(0,0,0,index); + texIdx.set(0,0,0,val); { LLFastTimer t(FTM_FACE_POSITION_STORE); @@ -1838,7 +1846,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } - if (rebuild_color) + if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) { LLFastTimer t(FTM_FACE_GEOM_COLOR); mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 233038daba..9664aa7dbe 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -149,7 +149,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y) { - S32 idx = (getRect().getHeight() - y) / ((S32) LLFontGL::getFontMonospace()->getLineHeight()+2) - 5; + S32 idx = (getRect().getHeight() - y) / (LLFontGL::getFontMonospace()->getLineHeight()+2) - 5; if (idx >= 0 && idx < (S32)ft_display_idx.size()) { @@ -552,7 +552,7 @@ void LLFastTimerView::draw() // update rectangle that includes timer bars mBarRect.mLeft = xleft; mBarRect.mRight = getRect().getWidth(); - mBarRect.mTop = ytop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); + mBarRect.mTop = ytop - (LLFontGL::getFontMonospace()->getLineHeight() + 4); mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT; y = ytop; @@ -846,7 +846,7 @@ void LLFastTimerView::draw() tdesc = llformat("%4.2f ms", ms); x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5; - y = mGraphRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight()); + y = mGraphRect.mTop - LLFontGL::getFontMonospace()->getLineHeight(); LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index f4b6dc2c81..575b613ccf 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -39,7 +39,7 @@ #include "llagent.h" #include "llclipboard.h" -#include "llinventoryclipboard.h" +#include "llclipboard.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llfloatersidepanelcontainer.h" @@ -1118,7 +1118,7 @@ BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) } void copy_slurl_to_clipboard_cb(std::string& slurl) { - gClipboard.copyFromString(utf8str_to_wstring(slurl)); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl),0,slurl.size()); LLSD args; args["SLURL"] = slurl; @@ -1187,7 +1187,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) } else if (action == "copy") { - LLInventoryClipboard::instance().store(mSelectedItemID); + LLClipboard::instance().copyToClipboard(mSelectedItemID, LLAssetType::AT_LANDMARK); } else if (action == "paste") { @@ -1211,13 +1211,13 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) BOOL LLFavoritesBarCtrl::isClipboardPasteable() const { - if (!LLInventoryClipboard::instance().hasContents()) + if (!LLClipboard::instance().hasContents()) { return FALSE; } LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); + LLClipboard::instance().pasteFromClipboard(objects); S32 count = objects.count(); for(S32 i = 0; i < count; i++) { @@ -1246,7 +1246,7 @@ void LLFavoritesBarCtrl::pastFromClipboard() const { LLInventoryItem* item = NULL; LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); + LLClipboard::instance().pasteFromClipboard(objects); S32 count = objects.count(); LLUUID parent_id(mFavoriteFolderId); for(S32 i = 0; i < count; i++) diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 08f9d26705..ec2493dd2e 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -670,7 +670,14 @@ void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures) switch (level) { case 0: - maskFeatures("Low"); + if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel) + { //only use fixed function by default if GL version < 3.0 or this is an intel graphics chip + maskFeatures("LowFixedFunction"); + } + else + { //same as low, but with "Basic Shaders" enabled + maskFeatures("Low"); + } break; case 1: maskFeatures("Mid"); @@ -779,6 +786,10 @@ void LLFeatureManager::applyBaseMasks() { maskFeatures("MapBufferRange"); } + if (gGLManager.mVRAM > 512) + { + maskFeatures("VRAMGT512"); + } // now mask by gpu string // Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 8024755e86..8986a694f9 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -49,7 +49,7 @@ LLFilePicker LLFilePicker::sInstance; #if LL_WINDOWS #define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0" #define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" -#define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0" +#define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0" #define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0" #ifdef _CORY_TESTING #define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0" @@ -593,8 +593,10 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB } else if (filter == FFLOAD_ANIM) { - if (fileInfo.filetype != 'BVH ' && - (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) + if (fileInfo.filetype != 'BVH ' && + fileInfo.filetype != 'ANIM' && + (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && + fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("anim"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) ) { result = false; @@ -1073,8 +1075,11 @@ void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer } // set the default path for this usage context. - picker->mContextToPathMap[picker->mCurContextName] = - gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); + const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); + if (cur_folder != NULL) + { + picker->mContextToPathMap[picker->mCurContextName] = cur_folder; + } gtk_widget_destroy(widget); gtk_main_quit(); @@ -1196,10 +1201,14 @@ static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker) LLTrans::getString("sound_files") + " (*.wav)"); } -static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker) +static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_pattern_filter_to_gtkchooser(picker, "*.bvh", - LLTrans::getString("animation_files") + " (*.bvh)"); + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, "*.bvh"); + gtk_file_filter_add_pattern(gfilter, "*.anim"); + std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)"; + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; } static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker) @@ -1351,7 +1360,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) filtername = add_wav_filter_to_gtkchooser(picker); break; case FFLOAD_ANIM: - filtername = add_bvh_filter_to_gtkchooser(picker); + filtername = add_anim_filter_to_gtkchooser(picker); break; case FFLOAD_COLLADA: filtername = add_collada_filter_to_gtkchooser(picker); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index aa66fcf9b8..0290e7cdf0 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -63,6 +63,11 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, // *TODO: Use a key to allow this not to be an effective singleton LLFloaterAvatarPicker* floater = LLFloaterReg::showTypedInstance<LLFloaterAvatarPicker>("avatar_picker"); + if (!floater) + { + llwarns << "Cannot instantiate avatar picker" << llendl; + return NULL; + } floater->mSelectionCallback = callback; floater->setAllowMultiple(allow_multiple); diff --git a/indra/newview/llfloaterbuildoptions.cpp b/indra/newview/llfloaterbuildoptions.cpp index 86c1bf0534..1b65d8d683 100644 --- a/indra/newview/llfloaterbuildoptions.cpp +++ b/indra/newview/llfloaterbuildoptions.cpp @@ -41,13 +41,9 @@ // Methods // -void commit_grid_mode(LLUICtrl *); - LLFloaterBuildOptions::LLFloaterBuildOptions(const LLSD& key) - : LLFloater(key), - mComboGridMode(NULL) + : LLFloater(key) { - mCommitCallbackRegistrar.add("GridOptions.gridMode", boost::bind(&commit_grid_mode,_1)); } LLFloaterBuildOptions::~LLFloaterBuildOptions() @@ -55,45 +51,9 @@ LLFloaterBuildOptions::~LLFloaterBuildOptions() BOOL LLFloaterBuildOptions::postBuild() { - mComboGridMode = getChild<LLComboBox>("combobox grid mode"); - return TRUE; } -void LLFloaterBuildOptions::setGridMode(EGridMode mode) -{ - mComboGridMode->setCurrentByIndex((S32)mode); -} - -void LLFloaterBuildOptions::updateGridMode() -{ - if (mComboGridMode) - { - S32 index = mComboGridMode->getCurrentIndex(); - mComboGridMode->removeall(); - - switch (mObjectSelection->getSelectType()) - { - case SELECT_TYPE_HUD: - mComboGridMode->add(getString("grid_screen_text")); - mComboGridMode->add(getString("grid_local_text")); - break; - case SELECT_TYPE_WORLD: - mComboGridMode->add(getString("grid_world_text")); - mComboGridMode->add(getString("grid_local_text")); - mComboGridMode->add(getString("grid_reference_text")); - break; - case SELECT_TYPE_ATTACHMENT: - mComboGridMode->add(getString("grid_attachment_text")); - mComboGridMode->add(getString("grid_local_text")); - mComboGridMode->add(getString("grid_reference_text")); - break; - } - - mComboGridMode->setCurrentByIndex(index); - } -} - // virtual void LLFloaterBuildOptions::onOpen(const LLSD& key) { @@ -105,10 +65,3 @@ void LLFloaterBuildOptions::onClose(bool app_quitting) { mObjectSelection = NULL; } - -void commit_grid_mode(LLUICtrl *ctrl) -{ - LLComboBox* combo = (LLComboBox*)ctrl; - - LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex()); -} diff --git a/indra/newview/llfloaterbuildoptions.h b/indra/newview/llfloaterbuildoptions.h index 7f3811bf1c..02c56cb6a9 100644 --- a/indra/newview/llfloaterbuildoptions.h +++ b/indra/newview/llfloaterbuildoptions.h @@ -35,7 +35,6 @@ #include "llfloater.h" #include "llselectmgr.h" -class LLComboBox; class LLObjectSelection; typedef LLSafeHandle<LLObjectSelection> LLObjectSelectionHandle; @@ -44,23 +43,17 @@ class LLFloaterBuildOptions : public LLFloater { public: - virtual BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); - void setGridMode(EGridMode mode); - void updateGridMode(); - private: - friend class LLFloaterReg; LLFloaterBuildOptions(const LLSD& key); ~LLFloaterBuildOptions(); - LLComboBox* mComboGridMode; LLObjectSelectionHandle mObjectSelection; }; #endif diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index ee8487b160..087b0007e1 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -239,8 +239,9 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj, // Compute icon for this item BOOL item_is_multi = FALSE; - if ( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED + 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)) { item_is_multi = TRUE; } diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index a7388d21a3..bca4b5e447 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -210,7 +210,9 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, LLSD row; BOOL item_is_multi = FALSE; - if ( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED ) + 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)) { item_is_multi = TRUE; } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index 2a3512e21a..ac33a05f42 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1,6 +1,6 @@ /** - * @file llfloateranimpreview.cpp - * @brief LLFloaterAnimPreview class implementation + * @file llfloaterbvhpreview.cpp + * @brief LLFloaterBvhPreview class implementation * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code @@ -26,7 +26,7 @@ #include "llviewerprecompiledheaders.h" -#include "llfloateranimpreview.h" +#include "llfloaterbvhpreview.h" #include "llbvhloader.h" #include "lldatapacker.h" @@ -115,9 +115,9 @@ std::string STATUS[] = }; //----------------------------------------------------------------------------- -// LLFloaterAnimPreview() +// LLFloaterBvhPreview() //----------------------------------------------------------------------------- -LLFloaterAnimPreview::LLFloaterAnimPreview(const std::string& filename) : +LLFloaterBvhPreview::LLFloaterBvhPreview(const std::string& filename) : LLFloaterNameDesc(filename) { mLastMouseX = 0; @@ -153,35 +153,35 @@ LLFloaterAnimPreview::LLFloaterAnimPreview(const std::string& filename) : //----------------------------------------------------------------------------- // setAnimCallbacks() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::setAnimCallbacks() +void LLFloaterBvhPreview::setAnimCallbacks() { - getChild<LLUICtrl>("playback_slider")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onSliderMove, this)); + getChild<LLUICtrl>("playback_slider")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onSliderMove, this)); - getChild<LLUICtrl>("preview_base_anim")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitBaseAnim, this)); + getChild<LLUICtrl>("preview_base_anim")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitBaseAnim, this)); getChild<LLUICtrl>("preview_base_anim")->setValue("Standing"); - getChild<LLUICtrl>("priority")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitPriority, this)); - getChild<LLUICtrl>("loop_check")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoop, this)); - getChild<LLUICtrl>("loop_in_point")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoopIn, this)); - getChild<LLUICtrl>("loop_in_point")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateLoopIn, this, _1)); - getChild<LLUICtrl>("loop_out_point")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoopOut, this)); - getChild<LLUICtrl>("loop_out_point")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateLoopOut, this, _1)); + getChild<LLUICtrl>("priority")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitPriority, this)); + getChild<LLUICtrl>("loop_check")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoop, this)); + getChild<LLUICtrl>("loop_in_point")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoopIn, this)); + getChild<LLUICtrl>("loop_in_point")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateLoopIn, this, _1)); + getChild<LLUICtrl>("loop_out_point")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoopOut, this)); + getChild<LLUICtrl>("loop_out_point")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateLoopOut, this, _1)); - getChild<LLUICtrl>("hand_pose_combo")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitHandPose, this)); + getChild<LLUICtrl>("hand_pose_combo")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitHandPose, this)); - getChild<LLUICtrl>("emote_combo")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEmote, this)); + getChild<LLUICtrl>("emote_combo")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEmote, this)); getChild<LLUICtrl>("emote_combo")->setValue("[None]"); - getChild<LLUICtrl>("ease_in_time")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEaseIn, this)); - getChild<LLUICtrl>("ease_in_time")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateEaseIn, this, _1)); - getChild<LLUICtrl>("ease_out_time")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEaseOut, this)); - getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateEaseOut, this, _1)); + getChild<LLUICtrl>("ease_in_time")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEaseIn, this)); + getChild<LLUICtrl>("ease_in_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseIn, this, _1)); + getChild<LLUICtrl>("ease_out_time")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEaseOut, this)); + getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseOut, this, _1)); } //----------------------------------------------------------------------------- // postBuild() //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::postBuild() +BOOL LLFloaterBvhPreview::postBuild() { LLKeyframeMotion* motionp = NULL; LLBVHLoader* loaderp = NULL; @@ -191,7 +191,7 @@ BOOL LLFloaterAnimPreview::postBuild() return FALSE; } - getChild<LLUICtrl>("name_form")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitName, this)); + getChild<LLUICtrl>("name_form")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitName, this)); childSetAction("ok_btn", onBtnOK, this); setDefaultBtn(); @@ -203,15 +203,15 @@ BOOL LLFloaterAnimPreview::postBuild() mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f); mPlayButton = getChild<LLButton>( "play_btn"); - mPlayButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnPlay, this)); + mPlayButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnPlay, this)); mPlayButton->setVisible(true); mPauseButton = getChild<LLButton>( "pause_btn"); - mPauseButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnPause, this)); + mPauseButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnPause, this)); mPauseButton->setVisible(false); mStopButton = getChild<LLButton>( "stop_btn"); - mStopButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnStop, this)); + mStopButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnStop, this)); getChildView("bad_animation_text")->setVisible(FALSE); @@ -363,9 +363,9 @@ BOOL LLFloaterAnimPreview::postBuild() } //----------------------------------------------------------------------------- -// LLFloaterAnimPreview() +// LLFloaterBvhPreview() //----------------------------------------------------------------------------- -LLFloaterAnimPreview::~LLFloaterAnimPreview() +LLFloaterBvhPreview::~LLFloaterBvhPreview() { mAnimPreview = NULL; @@ -375,7 +375,7 @@ LLFloaterAnimPreview::~LLFloaterAnimPreview() //----------------------------------------------------------------------------- // draw() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::draw() +void LLFloaterBvhPreview::draw() { LLFloater::draw(); LLRect r = getRect(); @@ -414,8 +414,11 @@ void LLFloaterAnimPreview::draw() //----------------------------------------------------------------------------- // resetMotion() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::resetMotion() +void LLFloaterBvhPreview::resetMotion() { + if (!mAnimPreview) + return; + LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); BOOL paused = avatarp->areAnimationsPaused(); @@ -450,7 +453,7 @@ void LLFloaterAnimPreview::resetMotion() //----------------------------------------------------------------------------- // handleMouseDown() //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLFloaterBvhPreview::handleMouseDown(S32 x, S32 y, MASK mask) { if (mPreviewRect.pointInRect(x, y)) { @@ -468,7 +471,7 @@ BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask) //----------------------------------------------------------------------------- // handleMouseUp() //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask) +BOOL LLFloaterBvhPreview::handleMouseUp(S32 x, S32 y, MASK mask) { gFocusMgr.setMouseCapture(FALSE); gViewerWindow->showCursor(); @@ -478,7 +481,7 @@ BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask) //----------------------------------------------------------------------------- // handleHover() //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask) +BOOL LLFloaterBvhPreview::handleHover(S32 x, S32 y, MASK mask) { MASK local_mask = mask & ~MASK_ALT; @@ -533,8 +536,11 @@ BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask) //----------------------------------------------------------------------------- // handleScrollWheel() //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) +BOOL LLFloaterBvhPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) { + if (!mAnimPreview) + return false; + mAnimPreview->zoom((F32)clicks * -0.2f); mAnimPreview->requestUpdate(); @@ -544,7 +550,7 @@ BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) //----------------------------------------------------------------------------- // onMouseCaptureLost() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onMouseCaptureLost() +void LLFloaterBvhPreview::onMouseCaptureLost() { gViewerWindow->showCursor(); } @@ -552,7 +558,7 @@ void LLFloaterAnimPreview::onMouseCaptureLost() //----------------------------------------------------------------------------- // onBtnPlay() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnPlay() +void LLFloaterBvhPreview::onBtnPlay() { if (!getEnabled()) return; @@ -576,7 +582,7 @@ void LLFloaterAnimPreview::onBtnPlay() //----------------------------------------------------------------------------- // onBtnPause() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnPause() +void LLFloaterBvhPreview::onBtnPause() { if (!getEnabled()) return; @@ -598,7 +604,7 @@ void LLFloaterAnimPreview::onBtnPause() //----------------------------------------------------------------------------- // onBtnStop() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnStop() +void LLFloaterBvhPreview::onBtnStop() { if (!getEnabled()) return; @@ -614,7 +620,7 @@ void LLFloaterAnimPreview::onBtnStop() //----------------------------------------------------------------------------- // onSliderMove() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onSliderMove() +void LLFloaterBvhPreview::onSliderMove() { if (!getEnabled()) return; @@ -639,7 +645,7 @@ void LLFloaterAnimPreview::onSliderMove() //----------------------------------------------------------------------------- // onCommitBaseAnim() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitBaseAnim() +void LLFloaterBvhPreview::onCommitBaseAnim() { if (!getEnabled()) return; @@ -668,9 +674,9 @@ void LLFloaterAnimPreview::onCommitBaseAnim() //----------------------------------------------------------------------------- // onCommitLoop() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoop() +void LLFloaterBvhPreview::onCommitLoop() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -687,9 +693,9 @@ void LLFloaterAnimPreview::onCommitLoop() //----------------------------------------------------------------------------- // onCommitLoopIn() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoopIn() +void LLFloaterBvhPreview::onCommitLoopIn() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -707,9 +713,9 @@ void LLFloaterAnimPreview::onCommitLoopIn() //----------------------------------------------------------------------------- // onCommitLoopOut() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoopOut() +void LLFloaterBvhPreview::onCommitLoopOut() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -727,9 +733,9 @@ void LLFloaterAnimPreview::onCommitLoopOut() //----------------------------------------------------------------------------- // onCommitName() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitName() +void LLFloaterBvhPreview::onCommitName() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -746,7 +752,7 @@ void LLFloaterAnimPreview::onCommitName() //----------------------------------------------------------------------------- // onCommitHandPose() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitHandPose() +void LLFloaterBvhPreview::onCommitHandPose() { if (!getEnabled()) return; @@ -757,7 +763,7 @@ void LLFloaterAnimPreview::onCommitHandPose() //----------------------------------------------------------------------------- // onCommitEmote() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEmote() +void LLFloaterBvhPreview::onCommitEmote() { if (!getEnabled()) return; @@ -768,9 +774,9 @@ void LLFloaterAnimPreview::onCommitEmote() //----------------------------------------------------------------------------- // onCommitPriority() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitPriority() +void LLFloaterBvhPreview::onCommitPriority() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -782,9 +788,9 @@ void LLFloaterAnimPreview::onCommitPriority() //----------------------------------------------------------------------------- // onCommitEaseIn() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEaseIn() +void LLFloaterBvhPreview::onCommitEaseIn() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -797,9 +803,9 @@ void LLFloaterAnimPreview::onCommitEaseIn() //----------------------------------------------------------------------------- // onCommitEaseOut() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEaseOut() +void LLFloaterBvhPreview::onCommitEaseOut() { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -812,9 +818,9 @@ void LLFloaterAnimPreview::onCommitEaseOut() //----------------------------------------------------------------------------- // validateEaseIn() //----------------------------------------------------------------------------- -bool LLFloaterAnimPreview::validateEaseIn(const LLSD& data) +bool LLFloaterBvhPreview::validateEaseIn(const LLSD& data) { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return false; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -832,9 +838,9 @@ bool LLFloaterAnimPreview::validateEaseIn(const LLSD& data) //----------------------------------------------------------------------------- // validateEaseOut() //----------------------------------------------------------------------------- -bool LLFloaterAnimPreview::validateEaseOut(const LLSD& data) +bool LLFloaterBvhPreview::validateEaseOut(const LLSD& data) { - if (!getEnabled()) + if (!getEnabled() || !mAnimPreview) return false; LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); @@ -852,7 +858,7 @@ bool LLFloaterAnimPreview::validateEaseOut(const LLSD& data) //----------------------------------------------------------------------------- // validateLoopIn() //----------------------------------------------------------------------------- -bool LLFloaterAnimPreview::validateLoopIn(const LLSD& data) +bool LLFloaterBvhPreview::validateLoopIn(const LLSD& data) { if (!getEnabled()) return false; @@ -880,7 +886,7 @@ bool LLFloaterAnimPreview::validateLoopIn(const LLSD& data) //----------------------------------------------------------------------------- // validateLoopOut() //----------------------------------------------------------------------------- -bool LLFloaterAnimPreview::validateLoopOut(const LLSD& data) +bool LLFloaterBvhPreview::validateLoopOut(const LLSD& data) { if (!getEnabled()) return false; @@ -909,7 +915,7 @@ bool LLFloaterAnimPreview::validateLoopOut(const LLSD& data) //----------------------------------------------------------------------------- // refresh() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::refresh() +void LLFloaterBvhPreview::refresh() { // Are we showing the play button (default) or the pause button? bool show_play = true; @@ -958,9 +964,9 @@ void LLFloaterAnimPreview::refresh() //----------------------------------------------------------------------------- // onBtnOK() //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnOK(void* userdata) +void LLFloaterBvhPreview::onBtnOK(void* userdata) { - LLFloaterAnimPreview* floaterp = (LLFloaterAnimPreview*)userdata; + LLFloaterBvhPreview* floaterp = (LLFloaterBvhPreview*)userdata; if (!floaterp->getEnabled()) return; if (floaterp->mAnimPreview) diff --git a/indra/newview/llfloateranimpreview.h b/indra/newview/llfloaterbvhpreview.h index f1ffb6547f..b81cc6e3a5 100644 --- a/indra/newview/llfloateranimpreview.h +++ b/indra/newview/llfloaterbvhpreview.h @@ -1,6 +1,6 @@ /** - * @file llfloateranimpreview.h - * @brief LLFloaterAnimPreview class definition + * @file llfloaterbvhpreview.h + * @brief LLFloaterBvhPreview class definition * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,14 +24,15 @@ * $/LicenseInfo$ */ -#ifndef LL_LLFLOATERANIMPREVIEW_H -#define LL_LLFLOATERANIMPREVIEW_H +#ifndef LL_LLFLOATERBVHPREVIEW_H +#define LL_LLFLOATERBVHPREVIEW_H #include "llassettype.h" #include "llfloaternamedesc.h" #include "lldynamictexture.h" #include "llcharacter.h" #include "llquaternion.h" +#include "llextendedstatus.h" class LLVOAvatar; class LLViewerJointMesh; @@ -67,11 +68,11 @@ protected: LLPointer<LLVOAvatar> mDummyAvatar; }; -class LLFloaterAnimPreview : public LLFloaterNameDesc +class LLFloaterBvhPreview : public LLFloaterNameDesc { public: - LLFloaterAnimPreview(const std::string& filename); - virtual ~LLFloaterAnimPreview(); + LLFloaterBvhPreview(const std::string& filename); + virtual ~LLFloaterBvhPreview(); BOOL postBuild(); @@ -128,4 +129,4 @@ protected: std::map<std::string, LLUUID> mIDList; }; -#endif // LL_LLFLOATERANIMPREVIEW_H +#endif // LL_LLFLOATERBVHPREVIEW_H diff --git a/indra/newview/llfloatereditsky.cpp b/indra/newview/llfloatereditsky.cpp index abee7b5dc9..352361ce9e 100644 --- a/indra/newview/llfloatereditsky.cpp +++ b/indra/newview/llfloatereditsky.cpp @@ -151,8 +151,8 @@ void LLFloaterEditSky::initCallbacks(void) getChild<LLUICtrl>("WLBlueHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, ¶m_mgr.mBlueHorizon)); // haze density, horizon, mult, and altitude - getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, ¶m_mgr.mHazeDensity)); - getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, ¶m_mgr.mHazeHorizon)); + getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, ¶m_mgr.mHazeDensity)); + getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, ¶m_mgr.mHazeHorizon)); getChild<LLUICtrl>("WLDensityMult")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, ¶m_mgr.mDensityMult)); getChild<LLUICtrl>("WLMaxAltitude")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, ¶m_mgr.mMaxAlt)); @@ -220,15 +220,14 @@ void LLFloaterEditSky::syncControls() setColorSwatch("WLBlueHorizon", param_mgr->mBlueHorizon, WL_BLUE_HORIZON_DENSITY_SCALE); // haze density, horizon, mult, and altitude - param_mgr->mHazeDensity = cur_params.getVector(param_mgr->mHazeDensity.mName, err); - childSetValue("WLHazeDensity", param_mgr->mHazeDensity.r); - param_mgr->mHazeHorizon = cur_params.getVector(param_mgr->mHazeHorizon.mName, err); - childSetValue("WLHazeHorizon", param_mgr->mHazeHorizon.r); - param_mgr->mDensityMult = cur_params.getVector(param_mgr->mDensityMult.mName, err); - childSetValue("WLDensityMult", param_mgr->mDensityMult.x * - param_mgr->mDensityMult.mult); - param_mgr->mMaxAlt = cur_params.getVector(param_mgr->mMaxAlt.mName, err); - childSetValue("WLMaxAltitude", param_mgr->mMaxAlt.x); + param_mgr->mHazeDensity = cur_params.getFloat(param_mgr->mHazeDensity.mName, err); + childSetValue("WLHazeDensity", (F32) param_mgr->mHazeDensity); + param_mgr->mHazeHorizon = cur_params.getFloat(param_mgr->mHazeHorizon.mName, err); + childSetValue("WLHazeHorizon", (F32) param_mgr->mHazeHorizon); + param_mgr->mDensityMult = cur_params.getFloat(param_mgr->mDensityMult.mName, err); + childSetValue("WLDensityMult", ((F32) param_mgr->mDensityMult) * param_mgr->mDensityMult.mult); + param_mgr->mMaxAlt = cur_params.getFloat(param_mgr->mMaxAlt.mName, err); + childSetValue("WLMaxAltitude", (F32) param_mgr->mMaxAlt); // blue density param_mgr->mBlueDensity = cur_params.getVector(param_mgr->mBlueDensity.mName, err); @@ -273,10 +272,10 @@ void LLFloaterEditSky::syncControls() childSetValue("WLCloudDetailDensity", param_mgr->mCloudDetail.b); // Cloud extras - param_mgr->mCloudCoverage = cur_params.getVector(param_mgr->mCloudCoverage.mName, err); - param_mgr->mCloudScale = cur_params.getVector(param_mgr->mCloudScale.mName, err); - childSetValue("WLCloudCoverage", param_mgr->mCloudCoverage.x); - childSetValue("WLCloudScale", param_mgr->mCloudScale.x); + param_mgr->mCloudCoverage = cur_params.getFloat(param_mgr->mCloudCoverage.mName, err); + param_mgr->mCloudScale = cur_params.getFloat(param_mgr->mCloudScale.mName, err); + childSetValue("WLCloudCoverage", (F32) param_mgr->mCloudCoverage); + childSetValue("WLCloudScale", (F32) param_mgr->mCloudScale); // cloud scrolling bool lockX = !param_mgr->mCurParams.getEnableCloudScrollX(); @@ -306,13 +305,13 @@ void LLFloaterEditSky::syncControls() childSetValue("WLCloudScrollX", param_mgr->mCurParams.getCloudScrollX() - 10.0f); childSetValue("WLCloudScrollY", param_mgr->mCurParams.getCloudScrollY() - 10.0f); - param_mgr->mDistanceMult = cur_params.getVector(param_mgr->mDistanceMult.mName, err); - childSetValue("WLDistanceMult", param_mgr->mDistanceMult.x); + param_mgr->mDistanceMult = cur_params.getFloat(param_mgr->mDistanceMult.mName, err); + childSetValue("WLDistanceMult", (F32) param_mgr->mDistanceMult); // Tweak extras - param_mgr->mWLGamma = cur_params.getVector(param_mgr->mWLGamma.mName, err); - childSetValue("WLGamma", param_mgr->mWLGamma.x); + param_mgr->mWLGamma = cur_params.getFloat(param_mgr->mWLGamma.mName, err); + childSetValue("WLGamma", (F32) param_mgr->mWLGamma); childSetValue("WLStarAlpha", param_mgr->mCurParams.getStarBrightness()); } diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index d495f20a9a..56051ff684 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -32,7 +32,7 @@ #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" -#include "llinventoryclipboard.h" +#include "llclipboard.h" #include "llagent.h" #include "llappearancemgr.h" @@ -90,6 +90,12 @@ public: if(mFloater) { mFloater->addGesture(inv_item,NULL,mFloater->getChild<LLScrollListCtrl>("gesture_list")); + + // EXP-1909 (Pasted gesture displayed twice) + // The problem is that addGesture is called here for the second time for the same item (which is copied) + // First time addGesture is called from LLFloaterGestureObserver::changed(), which is a callback for inventory + // change. So we need to refresh the gesture list to avoid duplicates. + mFloater->refreshAll(); } } }; @@ -391,11 +397,11 @@ bool LLFloaterGesture::isActionEnabled(const LLSD& command) std::string command_name = command.asString(); if("paste" == command_name) { - if(!LLInventoryClipboard::instance().hasContents()) + if(!LLClipboard::instance().hasContents()) return false; LLDynamicArray<LLUUID> ids; - LLInventoryClipboard::instance().retrieve(ids); + LLClipboard::instance().pasteFromClipboard(ids); for(LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++) { LLInventoryItem* item = gInventory.getItem(*it); @@ -490,27 +496,26 @@ void LLFloaterGesture::onActivateBtnClick() void LLFloaterGesture::onCopyPasteAction(const LLSD& command) { std::string command_name = command.asString(); - // since we select this comman inventory item had already arrived . + // Since we select this command, the inventory items must have already arrived if("copy_gesture" == command_name) { uuid_vec_t ids; getSelectedIds(ids); - // make sure that clopboard is empty - LLInventoryClipboard::instance().reset(); + // Make sure the clipboard is empty + LLClipboard::instance().reset(); for(uuid_vec_t::iterator it = ids.begin(); it != ids.end(); it++) { LLInventoryItem* item = gInventory.getItem(*it); if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE) { - LLInventoryClipboard::instance().add(item->getUUID()); + LLClipboard::instance().addToClipboard(item->getUUID(),LLAssetType::AT_GESTURE); } } } else if ("paste" == command_name) { - LLInventoryClipboard& clipbord = LLInventoryClipboard::instance(); LLDynamicArray<LLUUID> ids; - clipbord.retrieve(ids); + LLClipboard::instance().pasteFromClipboard(ids); if(ids.empty() || !gInventory.isCategoryComplete(mGestureFolderID)) return; LLInventoryCategory* gesture_dir = gInventory.getCategory(mGestureFolderID); @@ -530,11 +535,11 @@ void LLFloaterGesture::onCopyPasteAction(const LLSD& command) gesture_dir->getUUID(), getString("copy_name", string_args), cb); } } - clipbord.reset(); + LLClipboard::instance().reset(); } else if ("copy_uuid" == command_name) { - gClipboard.copyFromString(utf8str_to_wstring(mGestureList->getCurrentID().asString()), mGestureList->getCurrentID()); + LLClipboard::instance().copyToClipboard(mGestureList->getCurrentID(),LLAssetType::AT_GESTURE); } } diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index a34e0353ec..fb905eae11 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -1123,8 +1123,12 @@ bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const void LLPanelObjectTools::onClickSet() { + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2)); // grandparent is a floater, which can have a dependent - gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2))); + if (picker) + { + gFloaterView->getParentFloater(this)->addDependentFloater(picker); + } } void LLPanelObjectTools::onClickSetBySelection(void* data) diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index f9a403cf9f..116bd241c4 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -37,6 +37,7 @@ #include "llspinctrl.h" #include "llstartup.h" #include "lltextbox.h" +#include "llcombobox.h" #include "pipeline.h" // Linden library includes @@ -99,6 +100,12 @@ void LLFloaterHardwareSettings::refreshEnabledState() getChildView("vbo")->setEnabled(FALSE); } + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures") || + !gGLManager.mHasVertexBufferObject) + { + getChildView("texture compression")->setEnabled(FALSE); + } + // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance LLSpinCtrl* gamma_ctrl = getChild<LLSpinCtrl>("gamma"); gamma_ctrl->setEnabled(!gPipeline.canUseWindLightShaders()); @@ -142,6 +149,13 @@ BOOL LLFloaterHardwareSettings::postBuild() { childSetAction("OK", onBtnOK, this); + if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f) + { //remove FSAA settings above "4x" + LLComboBox* combo = getChild<LLComboBox>("fsaa"); + combo->remove("8x"); + combo->remove("16x"); + } + refresh(); center(); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 95da8ff948..ee18c95b34 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2739,7 +2739,12 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) void LLPanelLandAccess::onClickAddAccess() { - gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1)) ); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( + boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1)); + if (picker) + { + gFloaterView->getParentFloater(this)->addDependentFloater(picker); + } } void LLPanelLandAccess::callbackAvatarCBAccess(const uuid_vec_t& ids) @@ -2783,7 +2788,12 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data) // static void LLPanelLandAccess::onClickAddBanned() { - gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1))); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( + boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1)); + if (picker) + { + gFloaterView->getParentFloater(this)->addDependentFloater(picker); + } } // static diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp index 895e16adef..4f2a6ec1b7 100644 --- a/indra/newview/llfloatermediasettings.cpp +++ b/indra/newview/llfloatermediasettings.cpp @@ -312,3 +312,9 @@ bool LLFloaterMediaSettings::haveValuesChanged() const return values_changed; } +bool LLFloaterMediaSettings::instanceExists() +{ + return LLFloaterReg::findTypedInstance<LLFloaterMediaSettings>("media_settings"); +} + + diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h index ecc55d2cbc..1d25530986 100644 --- a/indra/newview/llfloatermediasettings.h +++ b/indra/newview/llfloatermediasettings.h @@ -45,6 +45,7 @@ public: /*virtual*/ void onClose(bool app_quitting); static LLFloaterMediaSettings* getInstance(); + static bool instanceExists(); static void apply(); static void initValues( const LLSD& media_settings , bool editable); static void clearValues( bool editable); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 9122e5a8f5..4b8beba546 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -4525,7 +4525,17 @@ void LLModelPreview::updateStatusMessages() } } - if (mFMP->childGetValue("physics_lod_combo").asString() == "From file") + + LLCtrlSelectionInterface* iface = fmp->childGetSelectionInterface("physics_lod_combo"); + S32 which_mode = 0; + S32 file_mode = 1; + if (iface) + { + which_mode = iface->getFirstSelectedIndex(); + file_mode = iface->getItemCount() - 1; + } + + if (which_mode == file_mode) { mFMP->childEnable("physics_file"); mFMP->childEnable("physics_browse"); @@ -5043,15 +5053,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(); @@ -5595,7 +5597,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..c522e6f734 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; @@ -390,9 +390,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/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 66f0fc3cd7..27b1c3b9cd 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -207,6 +207,25 @@ BOOL LLFloaterSoundPreview::postBuild() //----------------------------------------------------------------------------- +// LLFloaterAnimPreview() +//----------------------------------------------------------------------------- + +LLFloaterAnimPreview::LLFloaterAnimPreview(const LLSD& filename ) + : LLFloaterNameDesc(filename) +{ +} + +BOOL LLFloaterAnimPreview::postBuild() +{ + if (!LLFloaterNameDesc::postBuild()) + { + return FALSE; + } + getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this)); + return TRUE; +} + +//----------------------------------------------------------------------------- // LLFloaterScriptPreview() //----------------------------------------------------------------------------- diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h index 69bbccaf80..41643681ac 100644 --- a/indra/newview/llfloaternamedesc.h +++ b/indra/newview/llfloaternamedesc.h @@ -64,6 +64,13 @@ public: virtual BOOL postBuild(); }; +class LLFloaterAnimPreview : public LLFloaterNameDesc +{ +public: + LLFloaterAnimPreview(const LLSD& filename ); + virtual BOOL postBuild(); +}; + class LLFloaterScriptPreview : public LLFloaterNameDesc { public: diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index a333989e7e..173b0e538c 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -741,7 +741,8 @@ void LLFloaterPreference::onClose(bool app_quitting) void LLFloaterPreference::onOpenHardwareSettings() { - LLFloaterReg::showInstance("prefs_hardware_settings"); + LLFloater* floater = LLFloaterReg::showInstance("prefs_hardware_settings"); + addDependentFloater(floater, FALSE); } // static void LLFloaterPreference::onBtnOK() @@ -1800,7 +1801,46 @@ void LLPanelPreference::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl) } } +class LLPanelPreferencePrivacy : public LLPanelPreference +{ +public: + LLPanelPreferencePrivacy() + { + mAccountIndependentSettings.push_back("VoiceCallsFriendsOnly"); + mAccountIndependentSettings.push_back("AutoDisengageMic"); + } + + /*virtual*/ void saveSettings() + { + LLPanelPreference::saveSettings(); + + // Don't save (=erase from the saved values map) per-account privacy settings + // if we're not logged in, otherwise they will be reset to defaults on log off. + if (LLStartUp::getStartupState() != STATE_STARTED) + { + // Erase only common settings, assuming there are no color settings on Privacy page. + for (control_values_map_t::iterator it = mSavedValues.begin(); it != mSavedValues.end(); ) + { + const std::string setting = it->first->getName(); + if (std::find(mAccountIndependentSettings.begin(), + mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end()) + { + mSavedValues.erase(it++); + } + else + { + ++it; + } + } + } + } + +private: + std::list<std::string> mAccountIndependentSettings; +}; + static LLRegisterPanelClassWrapper<LLPanelPreferenceGraphics> t_pref_graph("panel_preference_graphics"); +static LLRegisterPanelClassWrapper<LLPanelPreferencePrivacy> t_pref_privacy("panel_preference_privacy"); BOOL LLPanelPreferenceGraphics::postBuild() { diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 7ee3294478..ec5994e917 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -198,15 +198,17 @@ public: virtual void saveSettings(); class Updater; + +protected: + typedef std::map<LLControlVariable*, LLSD> control_values_map_t; + control_values_map_t mSavedValues; + private: //for "Only friends and groups can call or IM me" static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&); //for "Show my Favorite Landmarks at Login" static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value); - typedef std::map<LLControlVariable*, LLSD> control_values_map_t; - control_values_map_t mSavedValues; - typedef std::map<std::string, LLColor4> string_color_map_t; string_color_map_t mSavedColors; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 676059779c..17850ff35d 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -650,7 +650,10 @@ void LLPanelRegionGeneralInfo::onClickKick() // in order to set up floater dependency LLFloater* parent_floater = gFloaterView->getParentFloater(this); LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE); - parent_floater->addDependentFloater(child_floater); + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } } void LLPanelRegionGeneralInfo::onKickCommit(const uuid_vec_t& ids) @@ -1470,7 +1473,10 @@ void LLPanelEstateInfo::onClickKickUser() // in order to set up floater dependency LLFloater* parent_floater = gFloaterView->getParentFloater(this); LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE); - parent_floater->addDependentFloater(child_floater); + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } } void LLPanelEstateInfo::onKickUserCommit(const uuid_vec_t& ids) @@ -1891,6 +1897,26 @@ void LLPanelEstateInfo::sendEstateAccessDelta(U32 flags, const LLUUID& agent_or_ gAgent.sendReliableMessage(); } +// static +void LLPanelEstateInfo::updateEstateOwnerName(const std::string& name) +{ + LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); + if (panelp) + { + panelp->setOwnerName(name); + } +} + +// static +void LLPanelEstateInfo::updateEstateName(const std::string& name) +{ + LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); + if (panelp) + { + panelp->getChildRef<LLTextBox>("estate_name").setText(name); + } +} + void LLPanelEstateInfo::updateControls(LLViewerRegion* region) { BOOL god = gAgent.isGodlike(); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index c402de66e8..e36ef4604b 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -33,6 +33,7 @@ #include "llfloater.h" #include "llhost.h" #include "llpanel.h" +#include "llextendedstatus.h" #include "llenvmanager.h" // for LLEnvironmentSettings @@ -293,6 +294,9 @@ public: void updateControls(LLViewerRegion* region); + static void updateEstateName(const std::string& name); + static void updateEstateOwnerName(const std::string& name); + virtual bool refreshFromRegion(LLViewerRegion* region); virtual bool estateUpdate(LLMessageSystem* msg); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index c08848b1ea..3ec1e372eb 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -285,7 +285,11 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) void LLFloaterReporter::onClickSelectAbuser() { - gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE )); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ); + if (picker) + { + gFloaterView->getParentFloater(this)->addDependentFloater(picker); + } } void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index cd98f7be57..7d68431710 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -31,6 +31,7 @@ #include "llfloater.h" #include "lluuid.h" #include "v3math.h" +#include "llextendedstatus.h" class LLAvatarName; class LLMessageSystem; diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index a0d1a32e12..b691db1049 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -106,7 +106,11 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std: if (objectp) { objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLViewerTexture::BOOST_UI)); - floater_label = llformat("%s(%.2f, %.2f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], objectp->getPositionRegion().mV[VY]); + floater_label = llformat("%s(%.0f, %.0f, %.0f)", + user_name.c_str(), + objectp->getPositionRegion().mV[VX], + objectp->getPositionRegion().mV[VY], + objectp->getPositionRegion().mV[VZ]); } else { diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 3434841d09..64c0dfa023 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -392,8 +392,12 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata) void LLFloaterSellLandUI::doSelectAgent() { + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE); // grandparent is a floater, in order to set up dependency - addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE)); + if (picker) + { + addDependentFloater(picker); + } } void LLFloaterSellLandUI::callbackAvatarPick(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index be7a53491d..5385977d95 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -59,7 +59,10 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na LLView* view = findChildView(panel_name, true); if (!view) return NULL; - openFloater(); + if (!getVisible()) + { + openFloater(); + } LLPanel* panel = NULL; diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp new file mode 100644 index 0000000000..2b34b72055 --- /dev/null +++ b/indra/newview/llfloatertexturefetchdebugger.cpp @@ -0,0 +1,390 @@ +/** + * @file llfloatertexturefetchdebugger.cpp + * @brief LLFloaterTextureFetchDebugger class definition + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatertexturefetchdebugger.h" + +#include "lluictrlfactory.h" +#include "llbutton.h" +#include "llspinctrl.h" +#include "llresmgr.h" + +#include "llmath.h" +#include "llviewerwindow.h" +#include "llappviewer.h" +#include "lltexturefetch.h" +#include "llviewercontrol.h" + +LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key) + : LLFloater(key), + mDebugger(NULL) +{ + setTitle("Texture Fetching Debugger Floater"); + + mCommitCallbackRegistrar.add("TexFetchDebugger.ChangeTexelPixelRatio", boost::bind(&LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio, this)); + + mCommitCallbackRegistrar.add("TexFetchDebugger.Start", boost::bind(&LLFloaterTextureFetchDebugger::onClickStart, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.Clear", boost::bind(&LLFloaterTextureFetchDebugger::onClickClear, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.Close", boost::bind(&LLFloaterTextureFetchDebugger::onClickClose, this)); + + mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.HTTPLoad", boost::bind(&LLFloaterTextureFetchDebugger::onClickHTTPLoad, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.Decode", boost::bind(&LLFloaterTextureFetchDebugger::onClickDecode, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.GLTexture", boost::bind(&LLFloaterTextureFetchDebugger::onClickGLTexture, this)); + + mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisCache", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisCache, this)); + mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisHTTP", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP, this)); +} +//---------------------------------------------- + +BOOL LLFloaterTextureFetchDebugger::postBuild(void) +{ + mDebugger = LLAppViewer::getTextureFetch()->getFetchDebugger(); + + //set states for buttons + mButtonStateMap["start_btn"] = true; + mButtonStateMap["close_btn"] = true; + mButtonStateMap["clear_btn"] = true; + mButtonStateMap["cacheread_btn"] = false; + mButtonStateMap["cachewrite_btn"] = false; + mButtonStateMap["http_btn"] = false; + mButtonStateMap["decode_btn"] = false; + mButtonStateMap["gl_btn"] = false; + + mButtonStateMap["refetchviscache_btn"] = true; + mButtonStateMap["refetchvishttp_btn"] = true; + + updateButtons(); + + getChild<LLUICtrl>("texel_pixel_ratio")->setValue(gSavedSettings.getF32("TexelPixelRatio")); + + return TRUE ; +} + +LLFloaterTextureFetchDebugger::~LLFloaterTextureFetchDebugger() +{ + //stop everything + mDebugger->stopDebug(); +} + +void LLFloaterTextureFetchDebugger::updateButtons() +{ + for(std::map<std::string, bool>::iterator iter = mButtonStateMap.begin(); iter != mButtonStateMap.end(); ++iter) + { + if(iter->second) + { + childEnable(iter->first.c_str()); + } + else + { + childDisable(iter->first.c_str()); + } + } +} + +void LLFloaterTextureFetchDebugger::disableButtons() +{ + childDisable("start_btn"); + childDisable("clear_btn"); + childDisable("cacheread_btn"); + childDisable("cachewrite_btn"); + childDisable("http_btn"); + childDisable("decode_btn"); + childDisable("gl_btn"); + childDisable("refetchviscache_btn"); + childDisable("refetchvishttp_btn"); +} + +void LLFloaterTextureFetchDebugger::idle() +{ + LLTextureFetchDebugger::e_debug_state state = mDebugger->getState(); + + if(mDebugger->update()) + { + switch(state) + { + case LLTextureFetchDebugger::IDLE: + break; + case LLTextureFetchDebugger::READ_CACHE: + mButtonStateMap["cachewrite_btn"] = true; + mButtonStateMap["decode_btn"] = true; + updateButtons(); + break; + case LLTextureFetchDebugger::WRITE_CACHE: + updateButtons(); + break; + case LLTextureFetchDebugger::DECODING: + mButtonStateMap["gl_btn"] = true; + updateButtons(); + break; + case LLTextureFetchDebugger::HTTP_FETCHING: + mButtonStateMap["cacheread_btn"] = true; + mButtonStateMap["cachewrite_btn"] = true; + mButtonStateMap["decode_btn"] = true; + updateButtons(); + break; + case LLTextureFetchDebugger::GL_TEX: + updateButtons(); + break; + case LLTextureFetchDebugger::REFETCH_VIS_CACHE: + updateButtons(); + case LLTextureFetchDebugger::REFETCH_VIS_HTTP: + updateButtons(); + break; + default: + break; + } + } +} + +//---------------------- +void LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio() +{ + gSavedSettings.setF32("TexelPixelRatio", getChild<LLUICtrl>("texel_pixel_ratio")->getValue().asReal()); +} + +void LLFloaterTextureFetchDebugger::onClickStart() +{ + disableButtons(); + + mDebugger->startDebug(); + + mButtonStateMap["start_btn"] = false; + mButtonStateMap["cacheread_btn"] = true; + mButtonStateMap["http_btn"] = true; + updateButtons(); +} + +void LLFloaterTextureFetchDebugger::onClickClose() +{ + setVisible(FALSE); + + //stop everything + mDebugger->stopDebug(); +} + +void LLFloaterTextureFetchDebugger::onClickClear() +{ + mButtonStateMap["start_btn"] = true; + mButtonStateMap["close_btn"] = true; + mButtonStateMap["clear_btn"] = true; + mButtonStateMap["cacheread_btn"] = false; + mButtonStateMap["cachewrite_btn"] = false; + mButtonStateMap["http_btn"] = false; + mButtonStateMap["decode_btn"] = false; + mButtonStateMap["gl_btn"] = false; + mButtonStateMap["refetchviscache_btn"] = true; + mButtonStateMap["refetchvishttp_btn"] = true; + updateButtons(); + + //stop everything + mDebugger->stopDebug(); + mDebugger->clearHistory(); +} + +void LLFloaterTextureFetchDebugger::onClickCacheRead() +{ + disableButtons(); + + mDebugger->debugCacheRead(); +} + +void LLFloaterTextureFetchDebugger::onClickCacheWrite() +{ + disableButtons(); + + mDebugger->debugCacheWrite(); +} + +void LLFloaterTextureFetchDebugger::onClickHTTPLoad() +{ + disableButtons(); + + mDebugger->debugHTTP(); +} + +void LLFloaterTextureFetchDebugger::onClickDecode() +{ + disableButtons(); + + mDebugger->debugDecoder(); +} + +void LLFloaterTextureFetchDebugger::onClickGLTexture() +{ + disableButtons(); + + mDebugger->debugGLTextureCreation(); +} + +void LLFloaterTextureFetchDebugger::onClickRefetchVisCache() +{ + disableButtons(); + + mDebugger->debugRefetchVisibleFromCache(); +} + +void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP() +{ + disableButtons(); + + mDebugger->debugRefetchVisibleFromHTTP(); +} + +void LLFloaterTextureFetchDebugger::draw() +{ + //total number of fetched textures + { + getChild<LLUICtrl>("total_num_fetched_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchedTextures())); + } + + //total number of fetching requests + { + getChild<LLUICtrl>("total_num_fetching_requests_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchingRequests())); + } + + //total number of cache hits + { + getChild<LLUICtrl>("total_num_cache_hits_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumCacheHits())); + } + + //total number of visible textures + { + getChild<LLUICtrl>("total_num_visible_tex_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchedTextures())); + } + + //total number of visible texture fetching requests + { + getChild<LLUICtrl>("total_num_visible_tex_fetch_req_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchingRequests())); + } + + //total number of fetched data + { + getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getFetchedData() >> 10)); + getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getDecodedData() >> 10)); + getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getFetchedPixels() / 1000000.f)); + } + + //total number of visible fetched data + { + getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getVisibleFetchedData() >> 10)); + getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getVisibleDecodedData() >> 10)); + } + + //total number of rendered fetched data + { + getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getRenderedData() >> 10)); + getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getRenderedDecodedData() >> 10)); + getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRenderedPixels() / 1000000.f)); + } + + //total time on cache readings + if(mDebugger->getCacheReadTime() < 0.f) + { + getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheReadTime())); + } + + //total time on cache writings + if(mDebugger->getCacheWriteTime() < 0.f) + { + getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheWriteTime())); + } + + //total time on decoding + if(mDebugger->getDecodeTime() < 0.f) + { + getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getDecodeTime())); + } + + //total time on gl texture creation + if(mDebugger->getGLCreationTime() < 0.f) + { + getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getGLCreationTime())); + } + + //total time on HTTP fetching + if(mDebugger->getHTTPTime() < 0.f) + { + getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getHTTPTime())); + } + + //total time on entire fetching + { + getChild<LLUICtrl>("total_time_fetch_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getTotalFetchingTime())); + } + + //total time on refetching visible textures from cache + if(mDebugger->getRefetchVisCacheTime() < 0.f) + { + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", std::string("----")); + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", std::string("----")); + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisCacheTime())); + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedData() >> 10)); + getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedPixels() / 1000000.f)); + } + + //total time on refetching visible textures from http + if(mDebugger->getRefetchVisHTTPTime() < 0.f) + { + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", std::string("----")); + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", std::string("----")); + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", std::string("----")); + } + else + { + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisHTTPTime())); + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedData() >> 10)); + getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedPixels() / 1000000.f)); + } + + LLFloater::draw(); +} diff --git a/indra/newview/llfloatertexturefetchdebugger.h b/indra/newview/llfloatertexturefetchdebugger.h new file mode 100644 index 0000000000..33012c6a3d --- /dev/null +++ b/indra/newview/llfloatertexturefetchdebugger.h @@ -0,0 +1,71 @@ +/** + * @file llfloatertexturefetchdebugger.h + * @brief texture fetching debugger window, debug use only + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H +#define LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H + +#include "llfloater.h" +class LLTextureFetchDebugger; + +class LLFloaterTextureFetchDebugger : public LLFloater +{ + friend class LLFloaterReg; +public: + /// initialize all the callbacks for the menu + + virtual BOOL postBuild() ; + virtual void draw() ; + + void onChangeTexelPixelRatio(); + + void onClickStart(); + void onClickClear(); + void onClickClose(); + + void onClickCacheRead(); + void onClickCacheWrite(); + void onClickHTTPLoad(); + void onClickDecode(); + void onClickGLTexture(); + + void onClickRefetchVisCache(); + void onClickRefetchVisHTTP(); +public: + void idle() ; + +private: + LLFloaterTextureFetchDebugger(const LLSD& key); + virtual ~LLFloaterTextureFetchDebugger(); + + void updateButtons(); + void disableButtons(); + +private: + LLTextureFetchDebugger* mDebugger; + std::map<std::string, bool> mButtonStateMap; +}; + +#endif // LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index bd5b5f4eb0..6978e6a430 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -36,6 +36,7 @@ #include "llagentcamera.h" #include "llbutton.h" #include "llcheckboxctrl.h" +#include "llcombobox.h" #include "lldraghandle.h" #include "llerror.h" #include "llfloaterbuildoptions.h" @@ -103,6 +104,7 @@ const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] = // Local prototypes +void commit_grid_mode(LLUICtrl *ctrl); void commit_select_component(void *data); void click_show_more(void*); void click_popup_info(void*); @@ -252,6 +254,7 @@ BOOL LLFloaterTools::postBuild() getChild<LLUICtrl>("checkbox uniform")->setValue((BOOL)gSavedSettings.getBOOL("ScaleUniform")); mCheckStretchTexture = getChild<LLCheckBoxCtrl>("checkbox stretch textures"); getChild<LLUICtrl>("checkbox stretch textures")->setValue((BOOL)gSavedSettings.getBOOL("ScaleStretchTextures")); + mComboGridMode = getChild<LLComboBox>("combobox grid mode"); mCheckStretchUniformLabel = getChild<LLTextBox>("checkbox uniform label"); // @@ -330,6 +333,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key) mCheckSnapToGrid(NULL), mBtnGridOptions(NULL), mTitleMedia(NULL), + mComboGridMode(NULL), mCheckStretchUniform(NULL), mCheckStretchTexture(NULL), mCheckStretchUniformLabel(NULL), @@ -386,6 +390,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key) mCommitCallbackRegistrar.add("BuildTool.commitRadioMove", boost::bind(&commit_radio_group_move,_1)); mCommitCallbackRegistrar.add("BuildTool.commitRadioEdit", boost::bind(&commit_radio_group_edit,_1)); + mCommitCallbackRegistrar.add("BuildTool.gridMode", boost::bind(&commit_grid_mode,_1)); mCommitCallbackRegistrar.add("BuildTool.selectComponent", boost::bind(&commit_select_component, this)); mCommitCallbackRegistrar.add("BuildTool.gridOptions", boost::bind(&LLFloaterTools::onClickGridOptions,this)); mCommitCallbackRegistrar.add("BuildTool.applyToSelection", boost::bind(&click_apply_to_selection, this)); @@ -687,6 +692,33 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) mRadioGroupEdit->setValue("radio select face"); } + if (mComboGridMode) + { + mComboGridMode->setVisible( edit_visible ); + S32 index = mComboGridMode->getCurrentIndex(); + mComboGridMode->removeall(); + + switch (mObjectSelection->getSelectType()) + { + case SELECT_TYPE_HUD: + mComboGridMode->add(getString("grid_screen_text")); + mComboGridMode->add(getString("grid_local_text")); + break; + case SELECT_TYPE_WORLD: + mComboGridMode->add(getString("grid_world_text")); + mComboGridMode->add(getString("grid_local_text")); + mComboGridMode->add(getString("grid_reference_text")); + break; + case SELECT_TYPE_ATTACHMENT: + mComboGridMode->add(getString("grid_attachment_text")); + mComboGridMode->add(getString("grid_local_text")); + mComboGridMode->add(getString("grid_reference_text")); + break; + } + + mComboGridMode->setCurrentByIndex(index); + } + // Snap to grid disabled for grab tool - very confusing if (mCheckSnapToGrid) mCheckSnapToGrid->setVisible( edit_visible /* || tool == LLToolGrab::getInstance() */ ); if (mBtnGridOptions) mBtnGridOptions->setVisible( edit_visible /* || tool == LLToolGrab::getInstance() */ ); @@ -1037,6 +1069,13 @@ void LLFloaterTools::setObjectType( LLPCode pcode ) gFocusMgr.setMouseCapture(NULL); } +void commit_grid_mode(LLUICtrl *ctrl) +{ + LLComboBox* combo = (LLComboBox*)ctrl; + + LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex()); +} + void LLFloaterTools::onClickGridOptions() { @@ -1144,7 +1183,7 @@ void LLFloaterTools::updateLandImpacts() childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", remaining_capacity_str); // Update land impacts info in the weights floater - LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::getTypedInstance<LLFloaterObjectWeights>("object_weights"); + LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::findTypedInstance<LLFloaterObjectWeights>("object_weights"); if(object_weights_floater) { object_weights_floater->updateLandImpacts(parcel); @@ -1234,6 +1273,7 @@ void LLFloaterTools::getMediaState() } } func; + // check if all faces have media(or, all dont have media) LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue( &func, bool_has_media ); diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 63ed9dc82b..7a19d093a4 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -33,6 +33,7 @@ class LLButton; class LLCheckBoxCtrl; +class LLComboBox; class LLPanelPermissions; class LLPanelObject; class LLPanelVolume; @@ -140,6 +141,7 @@ public: LLCheckBoxCtrl* mCheckSnapToGrid; LLButton* mBtnGridOptions; + LLComboBox* mComboGridMode; LLCheckBoxCtrl* mCheckStretchUniform; LLCheckBoxCtrl* mCheckStretchTexture; diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 428a02e9f0..1a17183efd 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); - LLNearbyChatBar::getInstance()->enableTranslationCheckbox(LLTranslate::isTranslationConfigured()); + LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); closeFloater(false); } diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index 030fed0575..227720bee3 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -145,7 +145,9 @@ void LLFloaterVoiceEffect::refreshEffectList() for (voice_effect_list_t::const_iterator it = template_list.begin(); it != template_list.end(); ++it) { const LLUUID& effect_id = it->second; - std::string effect_name = getString("effect_" + it->first); // will throw an error if the effect is not listed in the XML + + std::string localized_effect = "effect_" + it->first; + std::string effect_name = hasString(localized_effect) ? getString(localized_effect) : it->first; // XML contains localized effects names LLSD effect_properties = effect_interface->getVoiceEffectProperties(effect_id); diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 3b5c3663fb..3fe2518de6 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -169,7 +169,7 @@ void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) { // Make sure the layout of the browser control is updated, so this calculation is correct. - LLLayoutStack::updateClass(); + getChild<LLLayoutStack>("stack1")->updateLayout(); // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc. LLCoordWindow window_size; @@ -258,7 +258,7 @@ void LLFloaterWebContent::open_media(const Params& p) if (!p.preferred_media_size().isEmpty()) { - LLLayoutStack::updateClass(); + getChild<LLLayoutStack>("stack1")->updateLayout(); LLRect browser_rect = mWebBrowser->calcScreenRect(); LLCoordWindow window_size; getWindow()->getSize(&window_size); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index e0d7d67f7d..1fa194ab19 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -30,7 +30,7 @@ #include "llcallbacklist.h" #include "llinventorybridge.h" -#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone. +#include "llclipboard.h" // *TODO: remove this once hack below gone. #include "llinventoryfilter.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" @@ -165,6 +165,33 @@ void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) { } ///---------------------------------------------------------------------------- +/// Class LLFolderViewScrollContainer +///---------------------------------------------------------------------------- + +// virtual +const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const +{ + LLRect rect = LLRect::null; + if (mScrolledView) + { + LLFolderView* folder_view = dynamic_cast<LLFolderView*>(mScrolledView); + if (folder_view) + { + S32 height = folder_view->mRunningHeight; + + rect = mScrolledView->getRect(); + rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); + } + } + + return rect; +} + +LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) +: LLScrollContainer(p) +{} + +///---------------------------------------------------------------------------- /// Class LLFolderView ///---------------------------------------------------------------------------- LLFolderView::Params::Params() @@ -255,7 +282,7 @@ LLFolderView::LLFolderView(const Params& p) LLRect new_r = LLRect(rect.mLeft + ICON_PAD, rect.mTop - TEXT_PAD, rect.mRight, - rect.mTop - TEXT_PAD - llfloor(font->getLineHeight())); + rect.mTop - TEXT_PAD - font->getLineHeight()); text_p.rect(new_r); text_p.name(std::string(p.name)); text_p.font(font); @@ -388,7 +415,7 @@ void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); -// This view grows and shinks to enclose all of its children items and folders. +// This view grows and shrinks to enclose all of its children items and folders. S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) { if (getListener()->getUUID().notNull()) @@ -414,7 +441,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen getRoot()->getFilter()->getShowFolderState(); S32 total_width = LEFT_PAD; - S32 running_height = mDebugFilters ? llceil(LLFontGL::getFontMonospace()->getLineHeight()) : 0; + S32 running_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; S32 target_height = running_height; S32 parent_item_height = getRect().getHeight(); @@ -429,8 +456,8 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen } else { - folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? - (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter + folderp->setVisible((show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? + (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation)))); } if (folderp->getVisible()) @@ -527,15 +554,16 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) LLView::reshape(width, height, called_from_parent); scroll_rect = mScrollContainer->getContentWindowRect(); } - width = llmax(mMinWidth, scroll_rect.getWidth()); + width = llmax(mMinWidth, scroll_rect.getWidth()); height = llmax(mRunningHeight, scroll_rect.getHeight()); - // restrict width with scroll container's width - if (mUseEllipses) + // Restrict width within scroll container's width + if (mUseEllipses && mScrollContainer) + { width = scroll_rect.getWidth(); + } LLView::reshape(width, height, called_from_parent); - mReshapeSignal(mSelectedItems, FALSE); } @@ -769,7 +797,7 @@ void LLFolderView::sanitizeSelection() // if nothing selected after prior constraints... if (mSelectedItems.empty()) { - // ...select first available parent of original selection, or "My Inventory" otherwise + // ...select first available parent of original selection LLFolderViewItem* new_selection = NULL; if (original_selected_item) { @@ -912,7 +940,7 @@ void LLFolderView::draw() } else if (mShowEmptyMessage) { - if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) + if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) { mStatusText = LLTrans::getString("Searching"); } @@ -943,6 +971,9 @@ void LLFolderView::draw() // We should call this method to also notify parent about required rect. // See EXT-7564, EXT-7047. arrangeFromRoot(); + LLUI::popMatrix(); + LLUI::pushMatrix(); + LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); } } @@ -1014,6 +1045,24 @@ bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFol return false; } +// static +void LLFolderView::removeCutItems() +{ + // There's no item in "cut" mode on the clipboard -> exit + if (!LLClipboard::instance().isCutMode()) + return; + + // Get the list of clipboard item uuids and iterate through them + LLDynamicArray<LLUUID> objects; + LLClipboard::instance().pasteFromClipboard(objects); + for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) + { + gInventory.removeObject(*iter); + } +} + void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -1293,7 +1342,7 @@ BOOL LLFolderView::canCopy() const void LLFolderView::copy() { // *NOTE: total hack to clear the inventory clipboard - LLInventoryClipboard::instance().reset(); + LLClipboard::instance().reset(); S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { @@ -1334,7 +1383,7 @@ BOOL LLFolderView::canCut() const void LLFolderView::cut() { // clear the inventory clipboard - LLInventoryClipboard::instance().reset(); + LLClipboard::instance().reset(); S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { @@ -1348,6 +1397,7 @@ void LLFolderView::cut() listener->cutToClipboard(); } } + LLFolderView::removeCutItems(); } mSearchString.clear(); } @@ -1961,19 +2011,13 @@ void LLFolderView::deleteAllChildren() void LLFolderView::scrollToShowSelection() { - // If items are filtered while background fetch is in progress - // scrollbar resets to the first filtered item. See EXT-3981. - // However we allow scrolling for folder views with mAutoSelectOverride - // (used in Places SP) as an exception because the selection in them - // is not reset during items filtering. See STORM-133. - if ( (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mAutoSelectOverride) - && mSelectedItems.size() ) + if ( mSelectedItems.size() ) { mNeedsScroll = TRUE; } } -// If the parent is scroll containter, scroll it to make the selection +// If the parent is scroll container, scroll it to make the selection // is maximally visible. void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) { @@ -1994,7 +2038,7 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); - S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); + S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); @@ -2108,10 +2152,10 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) removeSelectedItems(); return true; } - - if ("copy" == action) - { - LLInventoryClipboard::instance().reset(); + if (("copy" == action) || ("cut" == action)) + { + // Clear the clipboard before we start adding things on it + LLClipboard::instance().reset(); } static const std::string change_folder_string = "change_folder_type_"; @@ -2192,46 +2236,56 @@ void LLFolderView::doIdle() arrangeAll(); } + if (mFilter->isModified() && mFilter->isNotDefault()) + { + mNeedsAutoSelect = TRUE; + } mFilter->clearModified(); - BOOL filter_modified_and_active = mCompletedFilterGeneration < mFilter->getCurrentGeneration() && - mFilter->isNotDefault(); - mNeedsAutoSelect = filter_modified_and_active && - !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); - // filter to determine visiblity before arranging + // filter to determine visibility before arranging filterFromRoot(); // automatically show matching items, and select first one if we had a selection - // do this every frame until user puts keyboard focus into the inventory window - // signaling the end of the automatic update - // only do this when mNeedsFilter is set, meaning filtered items have - // potentially changed if (mNeedsAutoSelect) { LLFastTimer t3(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if ((selected_itemp && !selected_itemp->getFiltered()) && !mAutoSelectOverride) + if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->potentiallyFiltered())) { - // select first filtered item - LLSelectFirstFilteredItem filter; - applyFunctorRecursively(filter); + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLSelectFirstFilteredItem functor; + applyFunctorRecursively(functor); } // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. if (mAutoSelectOverride && !mFilter->getFilterSubString().empty()) { - LLOpenFilteredFolders filter; - applyFunctorRecursively(filter); + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLOpenFilteredFolders functor; + applyFunctorRecursively(functor); } scrollToShowSelection(); } + BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration() + && !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); + if (filter_finished + || gFocusMgr.childHasKeyboardFocus(inventory_panel) + || gFocusMgr.childHasMouseCapture(inventory_panel)) + { + // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process + mNeedsAutoSelect = FALSE; + } + + // during filtering process, try to pin selected item's location on screen // this will happen when searching your inventory and when new items arrive - if (filter_modified_and_active) + if (!filter_finished) { // calculate rectangle to pin item to at start of animated rearrange if (!mPinningSelectedItem && !mSelectedItems.empty()) @@ -2297,7 +2351,7 @@ void LLFolderView::doIdle() { scrollToShowItem(mSelectedItems.back(), constraint_rect); // continue scrolling until animated layout change is done - if (!filter_modified_and_active + if (filter_finished && (!needsArrange() || !is_visible)) { mNeedsScroll = FALSE; diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 1d018b5e6a..da8bb15f8e 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -44,6 +44,7 @@ #include "lldepthstack.h" #include "lleditmenuhandler.h" #include "llfontgl.h" +#include "llscrollcontainer.h" #include "lltooldraganddrop.h" #include "llviewertexture.h" @@ -54,15 +55,33 @@ class LLInventoryModel; class LLPanel; class LLLineEditor; class LLMenuGL; -class LLScrollContainer; class LLUICtrl; class LLTextBox; +/** + * Class LLFolderViewScrollContainer + * + * A scroll container which provides the information about the height + * of currently displayed folder view contents. + * Used for updating vertical scroll bar visibility in inventory panel. + * See LLScrollContainer::calcVisibleSize(). + */ +class LLFolderViewScrollContainer : public LLScrollContainer +{ +public: + /*virtual*/ ~LLFolderViewScrollContainer() {}; + /*virtual*/ const LLRect getScrolledViewRect() const; + +protected: + LLFolderViewScrollContainer(const LLScrollContainer::Params& p); + friend class LLUICtrlFactory; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderView // -// Th LLFolderView represents the root level folder view object. It -// manages the screen region of the folder view. +// The LLFolderView represents the root level folder view object. +// It manages the screen region of the folder view. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler @@ -81,6 +100,9 @@ public: Params(); }; + + friend class LLFolderViewScrollContainer; + LLFolderView(const Params&); virtual ~LLFolderView( void ); @@ -88,7 +110,7 @@ public: virtual LLFolderView* getRoot() { return this; } - // FolderViews default to sort by name. This will change that, + // FolderViews default to sort by name. This will change that, // and resort the items if necessary. void setSortOrder(U32 order); void setFilterPermMask(PermissionMask filter_perm_mask); @@ -117,20 +139,20 @@ public: virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse); virtual BOOL addFolder( LLFolderViewFolder* folder); - // Finds width and height of this object and it's children. Also - // makes sure that this view and it's children are the right size. + // Find width and height of this object and its children. Also + // makes sure that this view and its children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); void arrangeAll() { mArrangeGeneration++; } S32 getArrangeGeneration() { return mArrangeGeneration; } - // applies filters to control visibility of inventory items + // Apply filters to control visibility of inventory items virtual void filter( LLInventoryFilter& filter); - // get the last selected item + // Get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); - // Record the selected item and pass it down the hierachy. + // Record the selected item and pass it down the hierarchy. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); @@ -140,13 +162,13 @@ public: // Called once a frame to update the selection if mSelectThisID has been set void updateSelection(); - // This method is used to toggle the selection of an item. Walks - // children, and keeps track of selected objects. + // This method is used to toggle the selection of an item. + // Walks children and keeps track of selected objects. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); virtual std::set<LLUUID> getSelectionList() const; - // make sure if ancestor is selected, descendents are not + // Make sure if ancestor is selected, descendents are not void sanitizeSelection(); void clearSelection(); void addToSelectionList(LLFolderViewItem* item); @@ -157,21 +179,22 @@ public: void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } - // deletion functionality + // Deletion functionality void removeSelectedItems(); + static void removeCutItems(); - // open the selected item. + // Open the selected item void openSelectedItems( void ); void propertiesSelectedItems( void ); - // change the folder type + // Change the folder type void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type); void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); - // copy & paste + // Copy & paste virtual void copy(); virtual BOOL canCopy() const; @@ -184,7 +207,7 @@ public: virtual void doDelete(); virtual BOOL canDoDelete() const; - // public rename functionality - can only start the process + // Public rename functionality - can only start the process void startRenamingSelectedItem( void ); // These functions were used when there was only one folderview, @@ -325,7 +348,7 @@ protected: /** * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. - * NOTE: For now it uses only to cut LLFolderViewItem::mLabel text to be used for Landmarks in Places Panel. + * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. */ bool mUseEllipses; // See EXT-719 diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index aee31ca033..06682dcbf1 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -75,7 +75,7 @@ public: virtual void move( LLFolderViewEventListener* parent_listener ) = 0; virtual BOOL isItemCopyable() const = 0; virtual BOOL copyToClipboard() const = 0; - virtual void cutToClipboard() = 0; + virtual BOOL cutToClipboard() const = 0; virtual BOOL isClipboardPasteable() const = 0; virtual void pasteFromClipboard() = 0; virtual void pasteLinkFromClipboard() = 0; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 8d6114c887..515e544452 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -40,6 +40,7 @@ #include "llviewerwindow.h" // Argh, only for setCursor() // linden library includes +#include "llclipboard.h" #include "llfocusmgr.h" // gFocusMgr #include "lltrans.h" @@ -220,6 +221,11 @@ BOOL LLFolderViewItem::potentiallyVisible() { // we haven't been checked against min required filter // or we have and we passed + return potentiallyFiltered(); +} + +BOOL LLFolderViewItem::potentiallyFiltered() +{ return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); } @@ -410,8 +416,8 @@ BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* roo } -// Finds width and height of this object and it's children. Also -// makes sure that this view and it's children are the right size. +// Finds width and height of this object and its children. Also +// makes sure that this view and its children are the right size. S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) { const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); @@ -423,7 +429,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) : 0; if (mLabelWidthDirty) { - mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mSearchableLabel); + mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT; mLabelWidthDirty = false; } @@ -1002,7 +1008,7 @@ void LLFolderViewItem::draw() LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; if (highlight_link) color = sLinkColor; if (in_library) color = sLibraryColor; - + F32 right_x = 0; F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); @@ -1045,7 +1051,7 @@ void LLFolderViewItem::draw() } if ((mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) - || (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() + || (LLInventoryModelBackgroundFetch::instance().folderFetchActive() && root_is_loading && mShowLoadStatus)) { @@ -1158,7 +1164,37 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) mNeedsSort = false; } - mHasVisibleChildren = hasFilteredDescendants(filter_generation); + // evaluate mHasVisibleChildren + mHasVisibleChildren = false; + if (hasFilteredDescendants(filter_generation)) + { + // We have to verify that there's at least one child that's not filtered out + bool found = false; + // Try the items first + for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + found = (itemp->getFiltered(filter_generation)); + if (found) + break; + } + if (!found) + { + // If no item found, try the folders + for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + found = ( folderp->getListener() + && (folderp->getFiltered(filter_generation) + || (folderp->getFilteredFolder(filter_generation) + && folderp->hasFilteredDescendants(filter_generation)))); + if (found) + break; + } + } + + mHasVisibleChildren = found; + } // calculate height as a single item (without any children), and reshapes rectangle to match LLFolderViewItem::arrange( width, height, filter_generation ); @@ -1311,7 +1347,7 @@ void LLFolderViewFolder::requestSort() void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) { - mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); + //mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); mCompletedFilterGeneration = generation; // only aggregate up if we are a lower (older) value if (recurse_up @@ -1345,7 +1381,8 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) && !mPassedFilter) // and did not pass the filter { // go ahead and flag this folder as done - mLastFilterGeneration = filter_generation; + mLastFilterGeneration = filter_generation; + mStringMatchOffset = std::string::npos; } else // filter self only on first pass through { @@ -2146,14 +2183,8 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) item->dirtyFilter(); - // Update the folder creation date if the folder has no creation date - bool setting_date = false; - const time_t item_creation_date = item->getCreationDate(); - if ((item_creation_date > 0) && (mCreationDate == 0)) - { - setCreationDate(item_creation_date); - setting_date = true; - } + // Update the folder creation date if the child is newer than our current date + setCreationDate(llmax<time_t>(mCreationDate, item->getCreationDate())); // Handle sorting requestArrange(); @@ -2163,11 +2194,8 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) LLFolderViewFolder* parentp = getParentFolder(); while (parentp) { - // Update the parent folder creation date - if (setting_date && (parentp->mCreationDate == 0)) - { - parentp->setCreationDate(item_creation_date); - } + // Update the folder creation date if the child is newer than our current date + parentp->setCreationDate(llmax<time_t>(parentp->mCreationDate, item->getCreationDate())); if (parentp->mSortFunction.isByDate()) { diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 2fc79f5765..3c7592046a 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -114,6 +114,7 @@ public: static const S32 ICON_PAD = 2; static const S32 ICON_WIDTH = 16; static const S32 TEXT_PAD = 1; + static const S32 TEXT_PAD_RIGHT = 4; static const S32 ARROW_SIZE = 12; static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; // animation parameters @@ -303,7 +304,8 @@ public: BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); S32 getIndentation() { return mIndentation; } - virtual BOOL potentiallyVisible(); // do we know for a fact that this item has been filtered out? + virtual BOOL potentiallyVisible(); // do we know for a fact that this item won't be displayed? + virtual BOOL potentiallyFiltered(); // do we know for a fact that this item has been filtered out? virtual BOOL getFiltered(); virtual BOOL getFiltered(S32 filter_generation); diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index 30858871ec..72bea8db10 100644 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -220,17 +220,25 @@ bool LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent, return res; } -void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, +bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, const LLInventoryCategory* cat, - const LLUUID& im_session_id) + const LLUUID& im_session_id, + const std::string& notification_name) { - if (!cat) return; + if (!cat) + { + return false; + } llinfos << "LLGiveInventory::giveInventoryCategory() - " << cat->getUUID() << llendl; - if (!isAgentAvatarValid()) return; + if (!isAgentAvatarValid()) + { + return false; + } + bool give_successful = true; // Test out how many items are being given. LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -253,24 +261,24 @@ void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, if (!complete) { LLNotificationsUtil::add("IncompleteInventory"); - return; + give_successful = false; } count = items.count() + cats.count(); if (count > MAX_ITEMS) { LLNotificationsUtil::add("TooManyItems"); - return; + give_successful = false; } else if (count == 0) { LLNotificationsUtil::add("NoItems"); - return; + give_successful = false; } - else + else if (give_successful) { if (0 == giveable.countNoCopy()) { - LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id); + give_successful = LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id); } else { @@ -279,9 +287,16 @@ void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, LLSD payload; payload["agent_id"] = to_agent; payload["folder_id"] = cat->getUUID(); + if (!notification_name.empty()) + { + payload["success_notification"] = notification_name; + } LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLGiveInventory::handleCopyProtectedCategory); + give_successful = false; } } + + return give_successful; } ////////////////////////////////////////////////////////////////////////// @@ -325,6 +340,7 @@ bool LLGiveInventory::handleCopyProtectedItem(const LLSD& notification, const LL S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLSD itmes = notification["payload"]["items"]; LLInventoryItem* item = NULL; + bool give_successful = true; switch(option) { case 0: // "Yes" @@ -343,15 +359,21 @@ bool LLGiveInventory::handleCopyProtectedItem(const LLSD& notification, const LL else { LLNotificationsUtil::add("CannotGiveItem"); + give_successful = false; } } + if (give_successful && notification["payload"]["success_notification"].isDefined()) + { + LLNotificationsUtil::add(notification["payload"]["success_notification"].asString()); + } break; default: // no, cancel, whatever, who cares, not yes. LLNotificationsUtil::add("TransactionCancelled"); + give_successful = false; break; } - return false; + return give_successful; } // static @@ -408,13 +430,14 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLInventoryCategory* cat = NULL; + bool give_successful = true; switch(option) { case 0: // "Yes" cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID()); if (cat) { - LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(), + give_successful = LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(), cat); LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -430,27 +453,37 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons gInventory.deleteObject(items.get(i)->getUUID()); } gInventory.notifyObservers(); + + if (give_successful && notification["payload"]["success_notification"].isDefined()) + { + LLNotificationsUtil::add(notification["payload"]["success_notification"].asString()); + } } else { LLNotificationsUtil::add("CannotGiveCategory"); + give_successful = false; } break; default: // no, cancel, whatever, who cares, not yes. LLNotificationsUtil::add("TransactionCancelled"); + give_successful = false; break; } - return false; + return give_successful; } // static -void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, +bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, const LLInventoryCategory* cat, const LLUUID& im_session_id) { - if (!cat) return; + if (!cat) + { + return false; + } llinfos << "LLGiveInventory::commitGiveInventoryCategory() - " << cat->getUUID() << llendl; @@ -467,6 +500,7 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, LLInventoryModel::EXCLUDE_TRASH, giveable); + bool give_successful = true; // MAX ITEMS is based on (sizeof(uuid)+2) * count must be < // MTUBYTES or 18 * count < 1200 => count < 1200/18 => // 66. I've cut it down a bit from there to give some pad. @@ -474,12 +508,12 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, if (count > MAX_ITEMS) { LLNotificationsUtil::add("TooManyItems"); - return; + give_successful = false; } else if (count == 0) { LLNotificationsUtil::add("NoItems"); - return; + give_successful = false; } else { @@ -545,6 +579,8 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, logInventoryOffer(to_agent, im_session_id); } + + return give_successful; } // EOF diff --git a/indra/newview/llgiveinventory.h b/indra/newview/llgiveinventory.h index e1e221c75b..85bc1ed49c 100644 --- a/indra/newview/llgiveinventory.h +++ b/indra/newview/llgiveinventory.h @@ -62,9 +62,10 @@ public: /** * Gives passed inventory category to specified avatar in specified session. */ - static void doGiveInventoryCategory(const LLUUID& to_agent, + static bool doGiveInventoryCategory(const LLUUID& to_agent, const LLInventoryCategory* item, - const LLUUID &session_id = LLUUID::null); + const LLUUID &session_id = LLUUID::null, + const std::string& notification = std::string()); // give inventory item functionality static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response); @@ -85,7 +86,7 @@ private: // give inventory category functionality static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response); - static void commitGiveInventoryCategory(const LLUUID& to_agent, + static bool commitGiveInventoryCategory(const LLUUID& to_agent, const LLInventoryCategory* cat, const LLUUID &im_session_id = LLUUID::null); diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index bbf66ca750..129cddda45 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -123,6 +123,22 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask) return handled; } +// virtual +BOOL LLGroupList::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLView::handleDoubleClick(x, y, mask); + // Handle double click only for the selected item in the list, skip clicks on empty space. + if (handled) + { + if (mDoubleClickSignal) + { + (*mDoubleClickSignal)(this, x, y, mask); + } + } + + return handled; +} + void LLGroupList::setNameFilter(const std::string& filter) { std::string filter_upper = filter; diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index d7051db891..8abf14b3d0 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -51,6 +51,7 @@ public: virtual void draw(); // from LLView /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); // from LLView void setNameFilter(const std::string& filter); void toggleIcons(); diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 122711a86d..dff310ecf9 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -138,7 +138,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f)); F32 right_x; - font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x); + font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x); LLUI::popMatrix(); gGL.popMatrix(); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 24a876c59a..579b6008ae 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -227,7 +227,7 @@ void LLHUDText::renderText() segment_iter != mTextSegments.end(); ++segment_iter ) { const LLFontGL* fontp = segment_iter->mFont; - y_offset -= fontp->getLineHeight(); + y_offset -= fontp->getLineHeight() - 1; // correction factor to match legacy font metrics U8 style = segment_iter->mStyle; LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW; @@ -480,8 +480,6 @@ void LLHUDText::updateSize() F32 width = 0.f; S32 max_lines = getMaxLines(); - //S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines); - //F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size()); S32 start_segment; if (max_lines < 0) start_segment = 0; @@ -491,7 +489,7 @@ void LLHUDText::updateSize() while (iter != mTextSegments.end()) { const LLFontGL* fontp = iter->mFont; - height += fontp->getLineHeight(); + height += fontp->getLineHeight() - 1; // correction factor to match legacy font metrics width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH)); ++iter; } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c8e48b0d42..0f0ae896a2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -119,6 +119,7 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, void LLIMFloaterContainer::onCloseFloater(LLUUID& id) { mSessions.erase(id); + setFocus(TRUE); } void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data) diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index cd71da7393..07d73c8c66 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -42,7 +42,7 @@ LLIMHandler::LLIMHandler(e_notification_type type, const LLSD& id) mType = type; // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createNotificationChannel(); + mChannel = LLChannelManager::getInstance()->createNotificationChannel()->getHandle(); } //-------------------------------------------------------------------------- @@ -55,13 +55,13 @@ void LLIMHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); } //-------------------------------------------------------------------------- bool LLIMHandler::processNotification(const LLSD& notify) { - if(!mChannel) + if(mChannel.isDead()) { return false; } @@ -72,7 +72,7 @@ bool LLIMHandler::processNotification(const LLSD& notify) return false; // arrange a channel on a screen - if(!mChannel->getVisible()) + if(!mChannel.get()->getVisible()) { initChannel(); } @@ -104,7 +104,7 @@ bool LLIMHandler::processNotification(const LLSD& notify) p.panel = im_box; p.can_be_stored = false; p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); @@ -113,7 +113,7 @@ bool LLIMHandler::processNotification(const LLSD& notify) } else if (notify["sigtype"].asString() == "delete") { - mChannel->killToastByNotificationID(notification->getID()); + mChannel.get()->killToastByNotificationID(notification->getID()); } return false; } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a856bd0bdc..4000570872 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -171,8 +171,8 @@ void LLIMModel::setActiveSessionID(const LLUUID& session_id) LLIMModel::LLIMModel() { - addNewMsgCallback(LLIMFloater::newIMCallback); - addNewMsgCallback(toast_callback); + addNewMsgCallback(boost::bind(&LLIMFloater::newIMCallback, _1)); + addNewMsgCallback(boost::bind(&toast_callback, _1)); } LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) @@ -2458,7 +2458,10 @@ void LLIMMgr::addMessage( make_ui_sound("UISndNewIncomingIMSession"); } - if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat)) + bool skip_message = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && + LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); + + if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message) { LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg); } @@ -2977,6 +2980,17 @@ bool LLIMMgr::isVoiceCall(const LLUUID& session_id) return im_session->mStartedAsIMCall; } +void LLIMMgr::addNotifiedNonFriendSessionID(const LLUUID& session_id) +{ + mNotifiedNonFriendSessions.insert(session_id); +} + +bool LLIMMgr::isNonFriendSessionNotified(const LLUUID& session_id) +{ + return mNotifiedNonFriendSessions.end() != mNotifiedNonFriendSessions.find(session_id); + +} + void LLIMMgr::noteOfflineUsers( const LLUUID& session_id, const LLDynamicArray<LLUUID>& ids) @@ -3223,7 +3237,6 @@ public: //just like a normal IM //this is just replicated code from process_improved_im //and should really go in it's own function -jwolk - LLChat chat; std::string message = message_params["message"].asString(); std::string name = message_params["from_name"].asString(); @@ -3241,14 +3254,7 @@ public: name, LLMute::flagTextChat); - BOOL is_linden = LLMuteList::getInstance()->isLinden(name); - std::string separator_string(": "); - - chat.mMuted = is_muted && !is_linden; - chat.mFromID = from_id; - chat.mFromName = name; - - if (!is_linden && is_busy) + if (is_busy || is_muted) { return; } diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index b1be26a169..7c2cd03d97 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -153,7 +153,6 @@ public: std::map<LLUUID, LLIMSession*> mId2SessionMap; typedef boost::signals2::signal<void(const LLSD&)> session_signal_t; - typedef boost::function<void(const LLSD&)> session_callback_t; session_signal_t mNewMsgSignal; session_signal_t mNoUnreadMsgsSignal; @@ -174,8 +173,8 @@ public: */ void processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id); - boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); } - boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); } + boost::signals2::connection addNewMsgCallback(const session_signal_t::slot_type& cb ) { return mNewMsgSignal.connect(cb); } + boost::signals2::connection addNoUnreadMsgsCallback(const session_signal_t::slot_type& cb ) { return mNoUnreadMsgsSignal.connect(cb); } /** * Create new session object in a model @@ -438,6 +437,10 @@ public: bool isVoiceCall(const LLUUID& session_id); + void addNotifiedNonFriendSessionID(const LLUUID& session_id); + + bool isNonFriendSessionNotified(const LLUUID& session_id); + private: /** @@ -465,6 +468,14 @@ private: typedef std::list <LLIMSessionObserver *> session_observers_list_t; session_observers_list_t mSessionObservers; + // EXP-901 + // If "Only friends and groups can IM me" option is ON but the user got message from non-friend, + // the user should be notified that to be able to see this message the option should be OFF. + // This set stores session IDs in which user was notified. Need to store this IDs so that the user + // be notified only one time per session with non-friend. + typedef std::set<LLUUID> notified_non_friend_sessions_t; + notified_non_friend_sessions_t mNotifiedNonFriendSessions; + LLSD mPendingInvitations; LLSD mPendingAgentListUpdates; }; diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index acc139c569..a7b93b8030 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -111,6 +111,7 @@ private: private: LLUUID mObjectID; + LLUUID mPreviousObjectID; S32 mObjectFace; viewer_media_t mMediaImpl; LLMediaEntry* mMediaEntry; @@ -249,6 +250,7 @@ void LLInspectObject::onClose(bool app_quitting) { // Release selection to deselect mObjectSelection = NULL; + mPreviousObjectID = mObjectID; getChild<LLMenuButton>("gear_btn")->hideMenu(); } @@ -266,6 +268,13 @@ void LLInspectObject::update() LLSelectNode* nodep = selection->getFirstRootNode(); if (!nodep) return; + // If we don't have fresh object info yet and it's the object we inspected last time, + // keep showing the previously retrieved data until we get the update. + if (!nodep->mValid && nodep->getObject()->getID() == mPreviousObjectID) + { + return; + } + updateButtons(nodep); updateName(nodep); updateDescription(nodep); diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index d7b82667d1..f4fe5dec01 100644 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -72,6 +72,8 @@ LLInspectToast::LLInspectToast(const LLSD& notification_id) : LLInspectToast::~LLInspectToast() { LLTransientFloaterMgr::getInstance()->removeControlView(this); + + mConnection.disconnect(); } // virtual diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index cebe93f042..b86c453d61 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -47,7 +47,7 @@ #include "llgiveinventory.h" #include "llimfloater.h" #include "llimview.h" -#include "llinventoryclipboard.h" +#include "llclipboard.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" @@ -73,7 +73,7 @@ #include "llwearablelist.h" // Marketplace outbox current disabled -#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 0 +#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1 #define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0 #define BLOCK_WORN_ITEMS_IN_OUTBOX 1 @@ -113,6 +113,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response bool confirm_attachment_rez(const LLSD& notification, const LLSD& response); void teleport_via_landmark(const LLUUID& asset_id); static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); +static bool check_category(LLInventoryModel* model, + const LLUUID& cat_id, + LLFolderView* active_folder_view, + LLInventoryFilter* filter); +static bool check_item(const LLUUID& item_id, + LLFolderView* active_folder_view, + LLInventoryFilter* filter); // Helper functions @@ -136,6 +143,42 @@ bool isMarketplaceSendAction(const std::string& action) return ("send_to_marketplace" == action); } +// Used by LLFolderBridge as callback for directory fetching recursion +class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver +{ +public: + LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids) : LLInventoryFetchDescendentsObserver(ids) {} + ~LLRightClickInventoryFetchDescendentsObserver() {} + virtual void execute(bool clear_observer = false); + virtual void done() + { + execute(true); + } +}; + +// Used by LLFolderBridge as callback for directory content items fetching +class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver +{ +public: + LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : LLInventoryFetchItemsObserver(ids) { }; + ~LLRightClickInventoryFetchObserver() {} + void execute(bool clear_observer = false) + { + if (clear_observer) + { + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + } + // we've downloaded all the items, so repaint the dialog + LLFolderBridge::staticFolderOptionsMenu(); + } + virtual void done() + { + execute(true); + } +}; + // +=================================================+ // | LLInvFVBridge | // +=================================================+ @@ -148,7 +191,7 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, mInvType(LLInventoryType::IT_NONE), mIsLink(FALSE) { - mInventoryPanel = inventory->getHandle(); + mInventoryPanel = inventory->getInventoryPanelHandle(); const LLInventoryObject* obj = getInventoryObject(); mIsLink = obj && obj->getIsLinkType(); } @@ -208,13 +251,27 @@ BOOL LLInvFVBridge::isLink() const /** * @brief Adds this item into clipboard storage */ -void LLInvFVBridge::cutToClipboard() +BOOL LLInvFVBridge::cutToClipboard() const +{ + const LLInventoryObject* obj = gInventory.getObject(mUUID); + if (obj && isItemMovable() && isItemRemovable()) + { + LLClipboard::instance().setCutMode(true); + return LLClipboard::instance().addToClipboard(mUUID); + } + return FALSE; +} + +BOOL LLInvFVBridge::copyToClipboard() const { - if(isItemMovable()) + const LLInventoryObject* obj = gInventory.getObject(mUUID); + if (obj && isItemCopyable()) { - LLInventoryClipboard::instance().cut(mUUID); + return LLClipboard::instance().addToClipboard(mUUID); } + return FALSE; } + // *TODO: make sure this does the right thing void LLInvFVBridge::showProperties() { @@ -389,6 +446,11 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* for(; it != end; ++it) { gInventory.moveObject((*it), trash_id); + LLViewerInventoryItem* item = gInventory.getItem(*it); + if (item) + { + model->updateItem(item); + } } // notify inventory observers. @@ -397,7 +459,8 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* BOOL LLInvFVBridge::isClipboardPasteable() const { - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) + // Return FALSE on degenerated cases: empty clipboard, no inventory, no agent + if (!LLClipboard::instance().hasContents() || !isAgentInventory()) { return FALSE; } @@ -407,37 +470,42 @@ BOOL LLInvFVBridge::isClipboardPasteable() const return FALSE; } - const LLUUID &agent_id = gAgent.getID(); + // In cut mode, whatever is on the clipboard is always pastable + if (LLClipboard::instance().isCutMode()) + { + return TRUE; + } + // In normal mode, we need to check each element of the clipboard to know if we can paste or not LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); + LLClipboard::instance().pasteFromClipboard(objects); S32 count = objects.count(); for(S32 i = 0; i < count; i++) { const LLUUID &item_id = objects.get(i); - // Can't paste folders + // Folders are pastable if all items in there are copyable const LLInventoryCategory *cat = model->getCategory(item_id); if (cat) { + LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, item_id); + if (!cat_br.isItemCopyable()) return FALSE; + // Skip to the next item in the clipboard + continue; } - const LLInventoryItem *item = model->getItem(item_id); - if (item) - { - if (!item->getPermissions().allowCopyBy(agent_id)) - { + // Each item must be copyable to be pastable + LLItemBridge item_br(mInventoryPanel.get(), mRoot, item_id); + if (!item_br.isItemCopyable()) return FALSE; } - } - } return TRUE; } BOOL LLInvFVBridge::isClipboardPasteableAsLink() const { - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) + if (!LLClipboard::instance().hasContents() || !isAgentInventory()) { return FALSE; } @@ -448,7 +516,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const } LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); + LLClipboard::instance().pasteFromClipboard(objects); S32 count = objects.count(); for(S32 i = 0; i < count; i++) { @@ -599,6 +667,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Copy")); } + items.push_back(std::string("Cut")); + if (!isItemMovable() || !isItemRemovable()) + { + disabled_items.push_back(std::string("Cut")); + } + if (canListOnMarketplace()) { items.push_back(std::string("Marketplace Separator")); @@ -798,7 +872,7 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const LLInventoryModel* LLInvFVBridge::getInventoryModel() const { - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); return panel ? panel->getModel() : NULL; } @@ -910,7 +984,7 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model, const LLUUID& new_parent_id, BOOL restamp) { - change_item_parent(model, item, new_parent_id, restamp); + model->changeItemParent(item, new_parent_id, restamp); } // static @@ -919,7 +993,7 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, const LLUUID& new_parent_id, BOOL restamp) { - change_category_parent(model, cat, new_parent_id, restamp); + model->changeCategoryParent(cat, new_parent_id, restamp); } LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, @@ -1278,6 +1352,12 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(buffer)); return; } + else if ("cut" == action) + { + cutToClipboard(); + LLFolderView::removeCutItems(); + return; + } else if ("copy" == action) { copyToClipboard(); @@ -1285,7 +1365,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) } else if ("paste" == action) { - // Single item only LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; @@ -1324,8 +1403,8 @@ void LLItemBridge::selectItem() LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem()); if(item && !item->isFinished()) { - item->fetchFromServer(); - //LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false); + //item->fetchFromServer(); + LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false); } } @@ -1660,16 +1739,6 @@ BOOL LLItemBridge::isItemCopyable() const return FALSE; } -BOOL LLItemBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - LLViewerInventoryItem* LLItemBridge::getItem() const { LLViewerInventoryItem* item = NULL; @@ -1703,16 +1772,20 @@ BOOL LLFolderBridge::isItemMovable() const LLInventoryObject* obj = getInventoryObject(); if(obj) { - return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())); + // If it's a protected type folder, we can't move it + if (LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())) + return FALSE; + return TRUE; } return FALSE; } void LLFolderBridge::selectItem() { + // Have no fear: the first thing start() does is to test if everything for that folder has been fetched... + LLInventoryModelBackgroundFetch::instance().start(getUUID(), true); } - // Iterate through a folder's children to determine if // all the children are removable. class LLIsItemRemovable : public LLFolderViewFunctor @@ -1738,7 +1811,7 @@ BOOL LLFolderBridge::isItemRemovable() const return FALSE; } - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); if (folderp) { @@ -1768,19 +1841,35 @@ BOOL LLFolderBridge::isUpToDate() const BOOL LLFolderBridge::isItemCopyable() const { - // Can copy folders to paste-as-link, but not for straight paste. - return gSavedSettings.getBOOL("InventoryLinking"); + // Folders are copyable if items in them are, recursively, copyable. + + // Get the content of the folder + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(mUUID,cat_array,item_array); + + // Check the items + LLInventoryModel::item_array_t item_array_copy = *item_array; + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + LLItemBridge item_br(mInventoryPanel.get(), mRoot, item->getUUID()); + if (!item_br.isItemCopyable()) + return FALSE; } -BOOL LLFolderBridge::copyToClipboard() const + // Check the folders + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) { - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); + LLViewerInventoryCategory* category = *iter; + LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, category->getUUID()); + if (!cat_br.isItemCopyable()) + return FALSE; + } + return TRUE; } - return FALSE; -} BOOL LLFolderBridge::isClipboardPasteable() const { @@ -1797,7 +1886,7 @@ BOOL LLFolderBridge::isClipboardPasteable() const } LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); + LLClipboard::instance().pasteFromClipboard(objects); const LLViewerInventoryCategory *current_cat = getCategory(); // Search for the direct descendent of current Friends subfolder among all pasted items, @@ -1835,7 +1924,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); const LLUUID ¤t_cat_id = current_cat->getUUID(); LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); + LLClipboard::instance().pasteFromClipboard(objects); S32 count = objects.count(); for(S32 i = 0; i < count; i++) { @@ -1959,6 +2048,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (!isAgentAvatarValid()) return FALSE; if (!isAgentInventory()) return FALSE; // cannot drag categories into library + LLInventoryPanel* destination_panel = mInventoryPanel.get(); + if (!destination_panel) return false; + + LLInventoryFilter* filter = destination_panel->getFilter(); + if (!filter) return false; + const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); @@ -2096,7 +2191,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // NOTE: The cargo id's count is a total of categories AND items but we err on the side of // prevention rather than letting too many folders into the hierarchy of the outbox, // when we're dragging the item to a new parent - dragged_folder_count += LLToolDragAndDrop::instance().getCargoIDsCount(); + dragged_folder_count += LLToolDragAndDrop::instance().getCargoCount(); } } @@ -2146,6 +2241,39 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } + if (is_movable) + { + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + is_movable = active_panel != NULL; + + // For a folder to pass the filter all its descendants are required to pass. + // We make this exception to allow reordering folders within an inventory panel, + // which has a filter applied, like Recent tab for example. + // There may be folders which are displayed because some of their descendants pass + // the filter, but other don't, and thus remain hidden. Without this check, + // such folders would not be allowed to be moved within a panel. + if (destination_panel == active_panel) + { + is_movable = true; + } + else + { + LLFolderView* active_folder_view = NULL; + + if (is_movable) + { + active_folder_view = active_panel->getRootFolder(); + is_movable = active_folder_view != NULL; + } + + if (is_movable) + { + // Check whether the folder being dragged from active inventory panel + // passes the filter of the destination panel. + is_movable = check_category(model, cat_id, active_folder_view, filter); + } + } + } // //-------------------------------------------------------------------------------- @@ -2240,7 +2368,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else { - accept = move_inv_category_world_to_agent(cat_id, mUUID, drop); + accept = move_inv_category_world_to_agent(cat_id, mUUID, drop, NULL, NULL, filter); } } else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) @@ -2285,7 +2413,8 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, const LLUUID& category_id, BOOL drop, void (*callback)(S32, void*), - void* user_data) + void* user_data, + LLInventoryFilter* filter) { // Make sure the object exists. If we allowed dragging from // anonymous objects, it would be possible to bypass @@ -2309,7 +2438,7 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, return FALSE; } - BOOL accept = TRUE; + BOOL accept = FALSE; BOOL is_move = FALSE; // coming from a task. Need to figure out if the person can @@ -2318,9 +2447,16 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, LLInventoryObject::object_list_t::iterator end = inventory_objects.end(); for ( ; it != end; ++it) { + LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(it->get()); + if (!item) + { + llwarns << "Invalid inventory item for drop" << llendl; + continue; + } + // coming from a task. Need to figure out if the person can // move/copy this item. - LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); + LLPermissions perm(item->getPermissions()); if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()))) // || gAgent.isGodlike()) @@ -2335,9 +2471,14 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, is_move = TRUE; accept = TRUE; } - else + + if (filter && accept) + { + accept = filter->check(item); + } + + if (!accept) { - accept = FALSE; break; } } @@ -2373,121 +2514,114 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, return accept; } -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver -{ -public: - LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : - LLInventoryFetchItemsObserver(ids), - mCopyItems(false) - { }; - LLRightClickInventoryFetchObserver(const uuid_vec_t& ids, - const LLUUID& cat_id, - bool copy_items) : - LLInventoryFetchItemsObserver(ids), - mCatID(cat_id), - mCopyItems(copy_items) - { }; - virtual void done() - { - // we've downloaded all the items, so repaint the dialog - LLFolderBridge::staticFolderOptionsMenu(); - - gInventory.removeObserver(this); - delete this; - } - -protected: - LLUUID mCatID; - bool mCopyItems; - -}; - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver -{ -public: - LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids, - bool copy_items) : - LLInventoryFetchDescendentsObserver(ids), - mCopyItems(copy_items) - {} - ~LLRightClickInventoryFetchDescendentsObserver() {} - virtual void done(); -protected: - bool mCopyItems; -}; - -void LLRightClickInventoryFetchDescendentsObserver::done() +void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) { - // Avoid passing a NULL-ref as mCompleteFolders.front() down to - // gInventory.collectDescendents() + // Bail out immediately if no descendents if( mComplete.empty() ) { llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; + if (clear_observer) + { dec_busy_count(); gInventory.removeObserver(this); delete this; + } return; } - // What we do here is get the complete information on the items in - // the library, and set up an observer that will wait for that to - // happen. - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mComplete.front(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH); - S32 count = item_array.count(); -#if 0 // HACK/TODO: Why? - // This early causes a giant menu to get produced, and doesn't seem to be needed. - if(!count) - { - llwarns << "Nothing fetched in category " << mCompleteFolders.front() - << llendl; + // Copy the list of complete fetched folders while "this" is still valid + uuid_vec_t completed_folder = mComplete; + + // Clean up, and remove this as an observer now since recursive calls + // could notify observers and throw us into an infinite loop. + if (clear_observer) + { dec_busy_count(); gInventory.removeObserver(this); delete this; - return; } -#endif - uuid_vec_t ids; - for(S32 i = 0; i < count; ++i) + for (uuid_vec_t::iterator current_folder = completed_folder.begin(); current_folder != completed_folder.end(); ++current_folder) { - ids.push_back(item_array.get(i)->getUUID()); - } + // Get the information on the fetched folder items and subfolders and fetch those + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array); - LLRightClickInventoryFetchObserver* outfit = new LLRightClickInventoryFetchObserver(ids, mComplete.front(), mCopyItems); + S32 item_count = item_array->count(); + S32 cat_count = cat_array->count(); + + // Move to next if current folder empty + if ((item_count == 0) && (cat_count == 0)) + { + continue; + } - // clean up, and remove this as an observer since the call to the - // outfit could notify observers and throw us into an infinite - // loop. - dec_busy_count(); - gInventory.removeObserver(this); - delete this; + uuid_vec_t ids; + LLRightClickInventoryFetchObserver* outfit = NULL; + LLRightClickInventoryFetchDescendentsObserver* categories = NULL; - // increment busy count and either tell the inventory to check & - // call done, or add this object to the inventory for observation. - inc_busy_count(); + // Fetch the items + if (item_count) + { + for (S32 i = 0; i < item_count; ++i) + { + ids.push_back(item_array->get(i)->getUUID()); + } + outfit = new LLRightClickInventoryFetchObserver(ids); + } + // Fetch the subfolders + if (cat_count) + { + for (S32 i = 0; i < cat_count; ++i) + { + ids.push_back(cat_array->get(i)->getUUID()); + } + categories = new LLRightClickInventoryFetchDescendentsObserver(ids); + } - // do the fetch + // Perform the item fetch + if (outfit) + { outfit->startFetch(); - outfit->done(); //Not interested in waiting and this will be right 99% of the time. + outfit->execute(); // Not interested in waiting and this will be right 99% of the time. + delete outfit; //Uncomment the following code for laggy Inventory UI. -/* if(outfit->isFinished()) + /* + if (outfit->isFinished()) { // everything is already here - call done. - outfit->done(); + outfit->execute(); + delete outfit; } else { - // it's all on it's way - add an observer, and the inventory + // it's all on its way - add an observer, and the inventory // will call done for us when everything is here. + inc_busy_count(); gInventory.addObserver(outfit); - }*/ + } + */ + } + // Perform the subfolders fetch : this is where we truly recurse down the folder hierarchy + if (categories) + { + categories->startFetch(); + if (categories->isFinished()) + { + // everything is already here - call done. + categories->execute(); + delete categories; + } + else + { + // it's all on its way - add an observer, and the inventory + // will call done for us when everything is here. + inc_busy_count(); + gInventory.addObserver(categories); + } + } + } } @@ -2606,6 +2740,12 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) modifyOutfit(TRUE); return; } + else if ("cut" == action) + { + cutToClipboard(); + LLFolderView::removeCutItems(); + return; + } else if ("copy" == action) { copyToClipboard(); @@ -2808,7 +2948,7 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re { // move it to the trash LLPreview::hide(mUUID); - remove_category(getInventoryModel(), mUUID); + getInventoryModel()->removeCategory(mUUID); return TRUE; } return FALSE; @@ -2820,20 +2960,65 @@ void LLFolderBridge::pasteFromClipboard() if(model && isClipboardPasteable()) { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + + LLDynamicArray<LLUUID> objects; + LLClipboard::instance().pasteFromClipboard(objects); + + if (move_is_into_outbox) + { + LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID); + + if (outbox_itemp) + { + LLToolDragAndDrop::instance().setCargoCount(objects.size()); + + BOOL can_list = TRUE; + + for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); + (iter != objects.end()) && (can_list == TRUE); + ++iter) + { + const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); + + if (item) + { + MASK mask = 0x0; + BOOL drop = FALSE; + EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(item->getActualType()); + void * cargo_data = (void *) item; + std::string tooltip_msg; + + can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + } + } + + LLToolDragAndDrop::instance().resetCargoCount(); + + if (can_list == FALSE) + { + // Notify user of failure somehow -- play error sound? modal dialog? + return; + } + } + } const LLUUID parent_id(mUUID); - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) { const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); - if (item) + LLInventoryObject *obj = model->getObject(item_id); + if (obj) { if (move_is_into_current_outfit || move_is_into_outfit) { @@ -2842,10 +3027,21 @@ void LLFolderBridge::pasteFromClipboard() dropToOutfit(item, move_is_into_current_outfit); } } - else if(LLInventoryClipboard::instance().isCutMode()) + else if (LLClipboard::instance().isCutMode()) + { + // Do a move to "paste" a "cut" + // move_inventory_item() is not enough, as we have to update inventory locally too + if (LLAssetType::AT_CATEGORY == obj->getType()) + { + LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); + llassert(vicat); + if (vicat) + { + changeCategoryParent(model, vicat, parent_id, FALSE); + } + } + else { - // move_inventory_item() is not enough, - //we have to update inventory locally too LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item); llassert(viitem); if (viitem) @@ -2853,6 +3049,19 @@ void LLFolderBridge::pasteFromClipboard() changeItemParent(model, viitem, parent_id, FALSE); } } + } + else + { + // Do a "copy" to "paste" a regular copy clipboard + if (LLAssetType::AT_CATEGORY == obj->getType()) + { + LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); + llassert(vicat); + if (vicat) + { + copy_inventory_category(model, vicat, parent_id); + } + } else { copy_inventory_item( @@ -2866,6 +3075,9 @@ void LLFolderBridge::pasteFromClipboard() } } } + // Change mode to paste for next paste + LLClipboard::instance().setCutMode(false); + } } void LLFolderBridge::pasteLinkFromClipboard() @@ -2874,13 +3086,22 @@ void LLFolderBridge::pasteLinkFromClipboard() if(model) { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + + if (move_is_into_outbox) + { + // Notify user of failure somehow -- play error sound? modal dialog? + return; + } const LLUUID parent_id(mUUID); LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); + LLClipboard::instance().pasteFromClipboard(objects); for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) @@ -2918,6 +3139,8 @@ void LLFolderBridge::pasteLinkFromClipboard() LLPointer<LLInventoryCallback>(NULL)); } } + // Change mode to paste for next paste + LLClipboard::instance().setCutMode(false); } } @@ -3175,16 +3398,19 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) folders.push_back(category->getUUID()); sSelf = getHandle(); - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); fetch->startFetch(); - inc_busy_count(); if (fetch->isFinished()) { + // Do not call execute() or done() here as if the folder is here, there's likely no point drilling down + // This saves lots of time as buildContextMenu() is called a lot + delete fetch; buildContextMenuFolderOptions(flags); } else { // it's all on its way - add an observer, and the inventory will call done for us when everything is here. + inc_busy_count(); gInventory.addObserver(fetch); } } @@ -3290,7 +3516,7 @@ void LLFolderBridge::createNewCategory(void* user_data) { LLFolderBridge* bridge = (LLFolderBridge*)user_data; if(!bridge) return; - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get()); + LLInventoryPanel* panel = bridge->mInventoryPanel.get(); if (!panel) return; LLInventoryModel* model = panel->getModel(); if(!model) return; @@ -3470,7 +3696,7 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) // use callback to rearrange favorite landmarks after adding // to have new one placed before target (on which it was dropped). See EXT-4312. LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback(); - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; if (drag_over_item && drag_over_item->getListener()) { @@ -3520,6 +3746,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if (!isAgentInventory()) return FALSE; // cannot drag into library if (!isAgentAvatarValid()) return FALSE; + LLInventoryPanel* destination_panel = mInventoryPanel.get(); + if (!destination_panel) return false; + + LLInventoryFilter* filter = destination_panel->getFilter(); + if (!filter) return false; + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); @@ -3529,7 +3761,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const BOOL move_is_into_favorites = (mUUID == favorites_id); const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); - const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); //(mUUID == outbox_id); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id); LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); @@ -3608,7 +3840,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); - int existing_item_count = LLToolDragAndDrop::instance().getCargoIDsCount(); + int existing_item_count = LLToolDragAndDrop::instance().getCargoCount(); if (master_folder != NULL) { @@ -3628,6 +3860,21 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } } + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + + // Check whether the item being dragged from active inventory panel + // passes the filter of the destination panel. + if (accept && active_panel) + { + LLFolderView* active_folder_view = active_panel->getRootFolder(); + if (!active_folder_view) return false; + + LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); + if (!fv_item) return false; + + accept = filter->check(fv_item); + } + if (accept && drop) { if (inv_item->getType() == LLAssetType::AT_GESTURE @@ -3637,15 +3884,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } // If an item is being dragged between windows, unselect everything in the active window // so that we don't follow the selection to its new location (which is very annoying). - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); - if (active_panel) - { - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - if (active_panel && (panel != active_panel)) + if (active_panel && (destination_panel != active_panel)) { active_panel->unSelectAll(); } - } //-------------------------------------------------------------------------------- // Destination folder logic @@ -3655,8 +3897,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // (only reorder the item in Favorites folder) if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites) { - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; + LLFolderViewItem* itemp = destination_panel->getRootFolder()->getDraggingOverItem(); if (itemp) { LLUUID srcItemId = inv_item->getUUID(); @@ -3760,6 +4001,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, accept = FALSE; } + // Check whether the item being dragged from in world + // passes the filter of the destination panel. + if (accept) + { + accept = filter->check(inv_item); + } + if (accept && drop) { LLMoveInv* move_inv = new LLMoveInv; @@ -3797,6 +4045,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, accept = !(move_is_into_current_outfit || move_is_into_outfit); } + // Check whether the item being dragged from notecard + // passes the filter of the destination panel. + if (accept) + { + accept = filter->check(inv_item); + } + if (accept && drop) { copy_inventory_from_notecard(mUUID, // Drop to the chosen destination folder @@ -3828,6 +4083,21 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, accept = can_move_to_landmarks(inv_item); } + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + + // Check whether the item being dragged from the library + // passes the filter of the destination panel. + if (accept && active_panel) + { + LLFolderView* active_folder_view = active_panel->getRootFolder(); + if (!active_folder_view) return false; + + LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); + if (!fv_item) return false; + + accept = filter->check(fv_item); + } + if (accept && drop) { // FAVORITES folder @@ -3862,6 +4132,69 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, return accept; } +// static +bool check_category(LLInventoryModel* model, + const LLUUID& cat_id, + LLFolderView* active_folder_view, + LLInventoryFilter* filter) +{ + if (!model || !active_folder_view || !filter) + return false; + + if (!filter->checkFolder(cat_id)) + { + return false; + } + + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + model->collectDescendents(cat_id, descendent_categories, descendent_items, TRUE); + + S32 num_descendent_categories = descendent_categories.count(); + S32 num_descendent_items = descendent_items.count(); + + if (num_descendent_categories + num_descendent_items == 0) + { + // Empty folder should be checked as any other folder view item. + // If we are filtering by date the folder should not pass because + // it doesn't have its own creation date. See LLInvFVBridge::getCreationDate(). + return check_item(cat_id, active_folder_view, filter); + } + + for (S32 i = 0; i < num_descendent_categories; ++i) + { + LLInventoryCategory* category = descendent_categories[i]; + if(!check_category(model, category->getUUID(), active_folder_view, filter)) + { + return false; + } + } + + for (S32 i = 0; i < num_descendent_items; ++i) + { + LLViewerInventoryItem* item = descendent_items[i]; + if(!check_item(item->getUUID(), active_folder_view, filter)) + { + return false; + } + } + + return true; +} + +// static +bool check_item(const LLUUID& item_id, + LLFolderView* active_folder_view, + LLInventoryFilter* filter) +{ + if (!active_folder_view || !filter) return false; + + LLFolderViewItem* fv_item = active_folder_view->getItemByID(item_id); + if (!fv_item) return false; + + return filter->check(fv_item); +} + // +=================================================+ // | LLTextureBridge | // +=================================================+ @@ -4184,7 +4517,7 @@ LLCallingCardBridge::~LLCallingCardBridge() void LLCallingCardBridge::refreshFolderViewItem() { - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; if (itemp) { @@ -4633,14 +4966,14 @@ void LLAnimationBridge::performAction(LLInventoryModel* model, std::string actio { if (getItem()) { - LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; - if ("playworld" == action) activate = LLPreviewAnim::PLAY; - if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; + LLSD::String activate = "NONE"; + if ("playworld" == action) activate = "Inworld"; + if ("playlocal" == action) activate = "Locally"; LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID)); if (preview) { - preview->activate(activate); + preview->play(activate); } } } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 871657a58a..dc9e88d54d 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -35,6 +35,7 @@ #include "llviewercontrol.h" #include "llwearable.h" +class LLInventoryFilter; class LLInventoryPanel; class LLInventoryModel; class LLMenuGL; @@ -105,8 +106,8 @@ public: virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); virtual void move(LLFolderViewEventListener* new_parent_bridge) {} virtual BOOL isItemCopyable() const { return FALSE; } - virtual BOOL copyToClipboard() const { return FALSE; } - virtual void cutToClipboard(); + virtual BOOL copyToClipboard() const; + virtual BOOL cutToClipboard() const; virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; virtual void pasteFromClipboard() {} @@ -161,7 +162,7 @@ protected: BOOL restamp); void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch); protected: - LLHandle<LLPanel> mInventoryPanel; + LLHandle<LLInventoryPanel> mInventoryPanel; LLFolderView* mRoot; const LLUUID mUUID; // item id LLInventoryType::EType mInvType; @@ -211,7 +212,6 @@ public: virtual BOOL renameItem(const std::string& new_name); virtual BOOL removeItem(); virtual BOOL isItemCopyable() const; - virtual BOOL copyToClipboard() const; virtual BOOL hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } @@ -274,7 +274,6 @@ public: virtual BOOL isItemCopyable() const; virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; - virtual BOOL copyToClipboard() const; static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type); @@ -645,7 +644,8 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, const LLUUID& category_id, BOOL drop, void (*callback)(S32, void*) = NULL, - void* user_data = NULL); + void* user_data = NULL, + LLInventoryFilter* filter = NULL); // Utility function to hide all entries except those in the list // Can be called multiple times on the same menu (e.g. if multiple items diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index d54bce4619..4573074c73 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -39,8 +39,11 @@ #include "llviewerfoldertype.h" // linden library includes +#include "llclipboard.h" #include "lltrans.h" +LLFastTimer::DeclareTimer FT_FILTER_CLIPBOARD("Filter Clipboard"); + LLInventoryFilter::FilterOps::FilterOps() : mFilterObjectTypes(0xffffffffffffffffULL), mFilterCategoryTypes(0xffffffffffffffffULL), @@ -88,11 +91,15 @@ LLInventoryFilter::~LLInventoryFilter() BOOL LLInventoryFilter::check(const LLFolderViewItem* item) { - // If it's a folder and we're showing all folders, return TRUE automatically. + // Clipboard cut items are *always* filtered so we need this value upfront + const LLFolderViewEventListener* listener = item->getListener(); + const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); + + // If it's a folder and we're showing all folders, return automatically. const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL); if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { - return TRUE; + return passed_clipboard; } mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; @@ -103,22 +110,60 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item) const BOOL passed = (passed_filtertype && passed_permissions && passed_filterlink && + passed_clipboard && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); return passed; } -bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) +bool LLInventoryFilter::check(const LLInventoryItem* item) { - // we're showing all folders, overriding filter - if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) + mSubStringMatchOffset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; + + const bool passed_filtertype = checkAgainstFilterType(item); + const bool passed_permissions = checkAgainstPermissions(item); + const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); + const bool passed = (passed_filtertype && + passed_permissions && + passed_clipboard && + (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); + + return passed; +} + +bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const +{ + if (!folder) { - return true; + llwarns << "The filter can not be checked on an invalid folder." << llendl; + llassert(false); // crash in development builds + return false; } const LLFolderViewEventListener* listener = folder->getListener(); + if (!listener) + { + llwarns << "Folder view event listener not found." << llendl; + llassert(false); // crash in development builds + return false; + } + const LLUUID folder_id = listener->getUUID(); + + return checkFolder(folder_id); +} + +bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const +{ + // Always check against the clipboard + const BOOL passed_clipboard = checkAgainstClipboard(folder_id); + // we're showing all folders, overriding filter + if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) + { + return passed_clipboard; + } + if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY) { // Can only filter categories for items in your inventory @@ -131,7 +176,7 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) return false; } - return true; + return passed_clipboard; } BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const @@ -223,10 +268,85 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con } } } - + return TRUE; } +bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const +{ + LLInventoryType::EType object_type = item->getInventoryType(); + const LLUUID object_id = item->getUUID(); + + const U32 filterTypes = mFilterOps.mFilterTypes; + + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_OBJECT + // Pass if this item's type is of the correct filter type + if (filterTypes & FILTERTYPE_OBJECT) + { + // If it has no type, pass it, unless it's a link. + if (object_type == LLInventoryType::IT_NONE) + { + if (item && item->getIsLinkType()) + { + return false; + } + } + else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0)) + { + return false; + } + } + + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_UUID + // Pass if this item is the target UUID or if it links to the target UUID + if (filterTypes & FILTERTYPE_UUID) + { + if (!item) return false; + + if (item->getLinkedUUID() != mFilterOps.mFilterUUID) + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_DATE + // Pass if this item is within the date range. + if (filterTypes & FILTERTYPE_DATE) + { + // We don't get the updated item creation date for the task inventory or + // a notecard embedded item. See LLTaskInvFVBridge::getCreationDate(). + return false; + } + + return true; +} + +// Items and folders that are on the clipboard or, recursively, in a folder which +// is on the clipboard must be filtered out if the clipboard is in the "cut" mode. +bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const +{ + if (LLClipboard::instance().isCutMode()) + { + LLFastTimer ft(FT_FILTER_CLIPBOARD); + LLUUID current_id = object_id; + LLInventoryObject *current_object = gInventory.getObject(object_id); + while (current_id.notNull() && current_object) + { + if (LLClipboard::instance().isOnClipboard(current_id)) + { + return false; + } + current_id = current_object->getParentUUID(); + if (current_id.notNull()) + { + current_object = gInventory.getObject(current_id); + } + } + } + return true; +} + BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const { const LLFolderViewEventListener* listener = item->getListener(); @@ -244,6 +364,17 @@ BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) co return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; } +bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) const +{ + if (!item) return false; + + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + PermissionMask perm = new_item->getPermissionMask(); + new_item = NULL; + + return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; +} + BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const { const LLFolderViewEventListener* listener = item->getListener(); @@ -271,6 +402,11 @@ std::string::size_type LLInventoryFilter::getStringMatchOffset() const return mSubStringMatchOffset; } +BOOL LLInventoryFilter::isDefault() const +{ + return !isNotDefault(); +} + // has user modified default filter params? BOOL LLInventoryFilter::isNotDefault() const { @@ -286,7 +422,7 @@ BOOL LLInventoryFilter::isNotDefault() const not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate); not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate); not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); - + return not_default; } @@ -464,7 +600,15 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date) mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date); setModified(); } - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + + if (areDateLimitsSet()) + { + mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + } + else + { + mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; + } } void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) @@ -476,10 +620,18 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) } if (!sl && isSinceLogoff()) { - setDateRange(0, time_max()); + setDateRange(time_min(), time_max()); setModified(); } - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + + if (areDateLimitsSet()) + { + mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + } + else + { + mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; + } } BOOL LLInventoryFilter::isSinceLogoff() const @@ -502,7 +654,7 @@ void LLInventoryFilter::setHoursAgo(U32 hours) bool are_date_limits_valid = mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max(); bool is_increasing = hours > mFilterOps.mHoursAgo; - bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo; + bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo && !isSinceLogoff(); // *NOTE: need to cache last filter time, in case filter goes stale BOOL less_restrictive = (are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo)) || !hours); @@ -524,7 +676,15 @@ void LLInventoryFilter::setHoursAgo(U32 hours) setModified(FILTER_RESTART); } } - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + + if (areDateLimitsSet()) + { + mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + } + else + { + mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; + } } void LLInventoryFilter::setFilterLinks(U64 filter_links) @@ -804,7 +964,7 @@ const std::string& LLInventoryFilter::getFilterText() filtered_by_all_types = FALSE; } - if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() + if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() && filtered_by_type && !filtered_by_all_types) { @@ -848,7 +1008,7 @@ void LLInventoryFilter::fromLLSD(LLSD& data) { if(data.has("filter_types")) { - setFilterObjectTypes((U32)data["filter_types"].asInteger()); + setFilterObjectTypes((U64)data["filter_types"].asInteger()); } if(data.has("min_date") && data.has("max_date")) @@ -974,3 +1134,10 @@ const std::string& LLInventoryFilter::getEmptyLookupMessage() const return mEmptyLookupMessage; } + +bool LLInventoryFilter::areDateLimitsSet() +{ + return mFilterOps.mMinDate != time_min() + || mFilterOps.mMaxDate != time_max() + || mFilterOps.mHoursAgo != 0; +} diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index bba24ac652..9e600c036f 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -32,6 +32,7 @@ class LLFolderViewItem; class LLFolderViewFolder; +class LLInventoryItem; class LLInventoryFilter { @@ -115,10 +116,15 @@ public: // + Execution And Results // +-------------------------------------------------------------------+ BOOL check(const LLFolderViewItem* item); - bool checkFolder(const LLFolderViewFolder* folder); + bool check(const LLInventoryItem* item); + bool checkFolder(const LLFolderViewFolder* folder) const; + bool checkFolder(const LLUUID& folder_id) const; BOOL checkAgainstFilterType(const LLFolderViewItem* item) const; + bool checkAgainstFilterType(const LLInventoryItem* item) const; BOOL checkAgainstPermissions(const LLFolderViewItem* item) const; + bool checkAgainstPermissions(const LLInventoryItem* item) const; BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const; + bool checkAgainstClipboard(const LLUUID& object_id) const; std::string::size_type getStringMatchOffset() const; @@ -157,6 +163,7 @@ public: // +-------------------------------------------------------------------+ // + Default // +-------------------------------------------------------------------+ + BOOL isDefault() const; BOOL isNotDefault() const; void markDefault(); void resetDefault(); @@ -175,6 +182,8 @@ public: void fromLLSD(LLSD& data); private: + bool areDateLimitsSet(); + struct FilterOps { FilterOps(); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index dd92188e9d..ab5b082915 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -54,7 +54,6 @@ #include "lliconctrl.h" #include "llimview.h" #include "llinventorybridge.h" -#include "llinventoryclipboard.h" #include "llinventorymodel.h" #include "llinventorypanel.h" #include "lllineeditor.h" @@ -109,91 +108,6 @@ void append_path(const LLUUID& id, std::string& path) path.append(temp); } -void change_item_parent(LLInventoryModel* model, - LLViewerInventoryItem* item, - const LLUUID& new_parent_id, - BOOL restamp) -{ - if (item->getParentUUID() != new_parent_id) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - new_item->setParent(new_parent_id); - new_item->updateParentOnServer(restamp); - model->updateItem(new_item); - model->notifyObservers(); - } -} - -void change_category_parent(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& new_parent_id, - BOOL restamp) -{ - if (!model || !cat) - { - return; - } - - // Can't move a folder into a child of itself. - if (model->isObjectDescendentOf(new_parent_id, cat->getUUID())) - { - return; - } - - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); - update.push_back(new_folder); - model->accountForUpdate(update); - - LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); - new_cat->setParent(new_parent_id); - new_cat->updateParentOnServer(restamp); - model->updateCategory(new_cat); - model->notifyObservers(); -} - -void remove_category(LLInventoryModel* model, const LLUUID& cat_id) -{ - if (!model || !get_is_category_removable(model, cat_id)) - { - return; - } - - // Look for any gestures and deactivate them - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); - - for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin(); - iter != descendent_items.end(); - ++iter) - { - const LLViewerInventoryItem* item = (*iter); - const LLUUID& item_id = item->getUUID(); - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureMgr::instance().isGestureActive(item_id)) - { - LLGestureMgr::instance().deactivateGesture(item_id); - } - } - - LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - if (cat) - { - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - change_category_parent(model, cat, trash_id, TRUE); - } -} - void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) { LLViewerInventoryCategory* cat; @@ -214,6 +128,49 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s model->notifyObservers(); } +void copy_inventory_category(LLInventoryModel* model, + LLViewerInventoryCategory* cat, + const LLUUID& parent_id, + const LLUUID& root_copy_id) +{ + // Create the initial folder + LLUUID new_cat_uuid = gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName()); + model->notifyObservers(); + + // We need to exclude the initial root of the copy to avoid recursively copying the copy, etc... + LLUUID root_id = (root_copy_id.isNull() ? new_cat_uuid : root_copy_id); + + // Get the content of the folder + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array); + + // Copy all the items + LLInventoryModel::item_array_t item_array_copy = *item_array; + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + new_cat_uuid, + std::string(), + LLPointer<LLInventoryCallback>(NULL)); + } + + // Copy all the folders + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLViewerInventoryCategory* category = *iter; + if (category->getUUID() != root_id) + { + copy_inventory_category(model, category, new_cat_uuid, root_id); + } + } +} + class LLInventoryCollectAllItems : public LLInventoryCollectFunctor { public: @@ -568,8 +525,7 @@ void move_to_outbox_cb_action(const LLSD& payload) LLUUID parent = viitem->getParentUUID(); - change_item_parent( - &gInventory, + gInventory.changeItemParent( viitem, dest_folder_id, false); @@ -596,7 +552,7 @@ void move_to_outbox_cb_action(const LLSD& payload) if (cat_array->empty() && item_array->empty()) { - remove_category(&gInventory, parent); + gInventory.removeCategory(parent); } if (parent == top_level_folder) @@ -670,7 +626,7 @@ void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; - change_item_parent(&gInventory, + gInventory.changeItemParent( viewer_inv_item, dest_folder, false); @@ -992,20 +948,24 @@ void LLSaveFolderState::setApply(BOOL apply) void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) { LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); + LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); + if(!bridge) return; + if(mApply) { // we're applying the open state - LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); - if(!bridge) return; LLUUID id(bridge->getUUID()); if(mOpenFolders.find(id) != mOpenFolders.end()) { - folder->setOpen(TRUE); + if (!folder->isOpen()) + { + folder->setOpen(TRUE); + } } else { // keep selected filter in its current state, this is less jarring to user - if (!folder->isSelected()) + if (!folder->isSelected() && folder->isOpen()) { folder->setOpen(FALSE); } @@ -1016,8 +976,6 @@ void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) // we're recording state at this point if(folder->isOpen()) { - LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); - if(!bridge) return; mOpenFolders.insert(bridge->getUUID()); } } @@ -1053,7 +1011,6 @@ void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) { item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } - item->getRoot()->scrollToShowSelection(); mItemSelected = TRUE; } } @@ -1067,7 +1024,6 @@ void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) { folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } - folder->getRoot()->scrollToShowSelection(); mItemSelected = TRUE; } } diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index ce2b89b22e..5cf9c528b0 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -57,20 +57,10 @@ void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id); void show_item_original(const LLUUID& item_uuid); -void change_item_parent(LLInventoryModel* model, - LLViewerInventoryItem* item, - const LLUUID& new_parent_id, - BOOL restamp); - -void change_category_parent(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& new_parent_id, - BOOL restamp); - -void remove_category(LLInventoryModel* model, const LLUUID& cat_id); - void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); +void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null); + // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index a71b699fdd..8092f3bf36 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -30,6 +30,7 @@ #include "llagent.h" #include "llagentwearables.h" #include "llappearancemgr.h" +#include "llclipboard.h" #include "llinventorypanel.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -46,6 +47,8 @@ #include "llviewerregion.h" #include "llcallbacklist.h" #include "llvoavatarself.h" +#include "llgesturemgr.h" +#include <typeinfo> //#define DIFF_INVENTORY_FILES #ifdef DIFF_INVENTORY_FILES @@ -1017,6 +1020,66 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id) } } +// Migrated from llinventoryfunctions +void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item, + const LLUUID& new_parent_id, + BOOL restamp) +{ + if (item->getParentUUID() == new_parent_id) + { + LL_DEBUGS("Inventory") << "'" << item->getName() << "' (" << item->getUUID() + << ") is already in folder " << new_parent_id << LL_ENDL; + } + else + { + LL_INFOS("Inventory") << "Moving '" << item->getName() << "' (" << item->getUUID() + << ") from " << item->getParentUUID() << " to folder " + << new_parent_id << LL_ENDL; + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); + update.push_back(new_folder); + accountForUpdate(update); + + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + new_item->setParent(new_parent_id); + new_item->updateParentOnServer(restamp); + updateItem(new_item); + notifyObservers(); + } +} + +// Migrated from llinventoryfunctions +void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, + const LLUUID& new_parent_id, + BOOL restamp) +{ + if (!cat) + { + return; + } + + // Can't move a folder into a child of itself. + if (isObjectDescendentOf(new_parent_id, cat->getUUID())) + { + return; + } + + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); + update.push_back(new_folder); + accountForUpdate(update); + + LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); + new_cat->setParent(new_parent_id); + new_cat->updateParentOnServer(restamp); + updateCategory(new_cat); + notifyObservers(); +} + // Delete a particular inventory object by ID. void LLInventoryModel::deleteObject(const LLUUID& id) { @@ -1110,50 +1173,82 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) return; } LLPointer<LLViewerInventoryCategory> cat = getCategory(id); - if(cat.notNull()) - { - // do the cache accounting - llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() - << llendl; - S32 descendents = cat->getDescendentCount(); - if(descendents > 0) - { - LLCategoryUpdate up(id, -descendents); - accountForUpdate(up); + if (cat.notNull()) + { + if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode()) + { + // Something on the clipboard is in "cut mode" and needs to be preserved + llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() + << " iterate and purge non hidden items" << llendl; + cat_array_t* categories; + item_array_t* items; + // Get the list of direct descendants in tha categoy passed as argument + getDirectDescendentsOf(id, categories, items); + std::vector<LLUUID> list_uuids; + // Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently) + // Note: we need to do that shallow copy as purging things will invalidate the categories or items lists + for (cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it) + { + list_uuids.push_back((*it)->getUUID()); + } + for (item_array_t::const_iterator it = items->begin(); it != items->end(); ++it) + { + list_uuids.push_back((*it)->getUUID()); + } + // Iterate through the list and only purge the UUIDs that are not on the clipboard + for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it) + { + if (!LLClipboard::instance().isOnClipboard(*it)) + { + purgeObject(*it); + } + } } + else + { + // Fast purge + // do the cache accounting + llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() + << llendl; + S32 descendents = cat->getDescendentCount(); + if(descendents > 0) + { + LLCategoryUpdate up(id, -descendents); + accountForUpdate(up); + } - // we know that descendent count is 0, aide since the - // accounting may actually not do an update, we should force - // it here. - cat->setDescendentCount(0); + // we know that descendent count is 0, however since the + // accounting may actually not do an update, we should force + // it here. + cat->setDescendentCount(0); + + // send it upstream + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("PurgeInventoryDescendents"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("InventoryData"); + msg->addUUID("FolderID", id); + gAgent.sendReliableMessage(); - // send it upstream - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("PurgeInventoryDescendents"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("InventoryData"); - msg->addUUID("FolderID", id); - gAgent.sendReliableMessage(); - - // unceremoniously remove anything we have locally stored. - cat_array_t categories; - item_array_t items; - collectDescendents(id, - categories, - items, - INCLUDE_TRASH); - S32 count = items.count(); - S32 i; - for(i = 0; i < count; ++i) - { - deleteObject(items.get(i)->getUUID()); - } - count = categories.count(); - for(i = 0; i < count; ++i) - { - deleteObject(categories.get(i)->getUUID()); + // unceremoniously remove anything we have locally stored. + cat_array_t categories; + item_array_t items; + collectDescendents(id, + categories, + items, + INCLUDE_TRASH); + S32 count = items.count(); + for(S32 i = 0; i < count; ++i) + { + deleteObject(items.get(i)->getUUID()); + } + count = categories.count(); + for(S32 i = 0; i < count; ++i) + { + deleteObject(categories.get(i)->getUUID()); + } } } } @@ -1664,6 +1759,7 @@ bool LLInventoryModel::loadSkeleton( update_map_t child_counts; cat_array_t categories; item_array_t items; + item_array_t possible_broken_links; cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded. std::string owner_id_str; owner_id.toString(owner_id_str); @@ -1712,7 +1808,7 @@ bool LLInventoryModel::loadSkeleton( LLViewerInventoryCategory* tcat = *cit; // we can safely ignore anything loaded from file, but - // not sent down in the skeleton. + // not sent down in the skeleton. Must have been removed from inventory. if(cit == not_cached) { continue; @@ -1750,6 +1846,8 @@ bool LLInventoryModel::loadSkeleton( // Add all the items loaded which are parented to a // category with a correctly cached parent S32 bad_link_count = 0; + S32 good_link_count = 0; + S32 recovered_link_count = 0; cat_map_t::iterator unparented = mCategoryMap.end(); for(item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); @@ -1766,26 +1864,56 @@ bool LLInventoryModel::loadSkeleton( // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache. if (item->getIsBrokenLink()) { - bad_link_count++; + //bad_link_count++; lldebugs << "Attempted to add cached link item without baseobj present ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl; - invalid_categories.insert(cit->second); + possible_broken_links.push_back(item); continue; } + else if (item->getIsLinkType()) + { + good_link_count++; + } addItem(item); cached_item_count += 1; ++child_counts[cat->getUUID()]; } } } - if (bad_link_count > 0) + if (possible_broken_links.size() > 0) { - llinfos << "Attempted to add " << bad_link_count - << " cached link items without baseobj present. " - << "The corresponding categories were invalidated." << llendl; + for(item_array_t::const_iterator item_iter = possible_broken_links.begin(); + item_iter != possible_broken_links.end(); + ++item_iter) + { + LLViewerInventoryItem *item = (*item_iter).get(); + const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID()); + const LLViewerInventoryCategory* cat = cit->second.get(); + if (item->getIsBrokenLink()) + { + bad_link_count++; + invalid_categories.insert(cit->second); + //llinfos << "link still broken: " << item->getName() << " in folder " << cat->getName() << llendl; + } + else + { + // was marked as broken because of loading order, its actually fine to load + addItem(item); + cached_item_count += 1; + ++child_counts[cat->getUUID()]; + recovered_link_count++; + } + } + + llinfos << "Attempted to add " << bad_link_count + << " cached link items without baseobj present. " + << good_link_count << " link items were successfully added. " + << recovered_link_count << " links added in recovery. " + << "The corresponding categories were invalidated." << llendl; } + } else { @@ -2683,7 +2811,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) { LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; titem->unpackMessage(msg, _PREHASH_ItemData, i); - llinfos << "unpaked item '" << titem->getName() << "' in " + llinfos << "unpacked item '" << titem->getName() << "' in " << titem->getParentUUID() << llendl; U32 callback_id; msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id); @@ -2931,21 +3059,77 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT void LLInventoryModel::removeItem(const LLUUID& item_id) { LLViewerInventoryItem* item = getItem(item_id); - const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH); - if (item && item->getParentUUID() != new_parent) + if (! item) { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - accountForUpdate(update); + LL_WARNS("Inventory") << "couldn't find inventory item " << item_id << LL_ENDL; + } + else + { + const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (new_parent.notNull()) + { + LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL; + changeItemParent(item, new_parent, TRUE); + } + } +} - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - new_item->setParent(new_parent); - new_item->updateParentOnServer(TRUE); - updateItem(new_item); - notifyObservers(); +void LLInventoryModel::removeCategory(const LLUUID& category_id) +{ + if (! get_is_category_removable(this, category_id)) + { + return; + } + + // Look for any gestures and deactivate them + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + collectDescendents(category_id, descendent_categories, descendent_items, FALSE); + + for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin(); + iter != descendent_items.end(); + ++iter) + { + const LLViewerInventoryItem* item = (*iter); + const LLUUID& item_id = item->getUUID(); + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureMgr::instance().isGestureActive(item_id)) + { + LLGestureMgr::instance().deactivateGesture(item_id); + } + } + + LLViewerInventoryCategory* cat = getCategory(category_id); + if (cat) + { + const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (trash_id.notNull()) + { + changeCategoryParent(cat, trash_id, TRUE); + } + } +} + +void LLInventoryModel::removeObject(const LLUUID& object_id) +{ + LLInventoryObject* obj = getObject(object_id); + if (dynamic_cast<LLViewerInventoryItem*>(obj)) + { + removeItem(object_id); + } + else if (dynamic_cast<LLViewerInventoryCategory*>(obj)) + { + removeCategory(object_id); + } + else if (obj) + { + LL_WARNS("Inventory") << "object ID " << object_id + << " is an object of unrecognized class " + << typeid(*obj).name() << LL_ENDL; + } + else + { + LL_WARNS("Inventory") << "object ID " << object_id << " not found" << LL_ENDL; } } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 7cd85c4ab7..8382e875b4 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -306,6 +306,16 @@ public: // observer notification, or server update is performed. void moveObject(const LLUUID& object_id, const LLUUID& cat_id); + // Migrated from llinventoryfunctions + void changeItemParent(LLViewerInventoryItem* item, + const LLUUID& new_parent_id, + BOOL restamp); + + // Migrated from llinventoryfunctions + void changeCategoryParent(LLViewerInventoryCategory* cat, + const LLUUID& new_parent_id, + BOOL restamp); + //-------------------------------------------------------------------- // Delete //-------------------------------------------------------------------- @@ -315,8 +325,13 @@ public: // consistent internal state. No cache accounting, observer // notification, or server update is performed. void deleteObject(const LLUUID& id); + /// move Item item_id to Trash void removeItem(const LLUUID& item_id); - + /// move Category category_id to Trash + void removeCategory(const LLUUID& category_id); + /// removeItem() or removeCategory(), whichever is appropriate + void removeObject(const LLUUID& object_id); + // Delete a particular inventory object by ID, and delete it from // the server. Also updates linked items. void purgeObject(const LLUUID& id); diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 91fdd67806..f4d0110b0f 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -43,6 +43,7 @@ const S32 MAX_FETCH_RETRIES = 10; LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() : mBackgroundFetchActive(FALSE), + mFolderFetchActive(false), mAllFoldersFetched(FALSE), mRecursiveInventoryFetchStarted(FALSE), mRecursiveLibraryFetchStarted(FALSE), @@ -50,7 +51,7 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() : mMinTimeBetweenFetches(0.3f), mMaxTimeBetweenFetches(10.f), mTimelyFetchPending(FALSE), - mBulkFetchCount(0) + mFetchCount(0) { } @@ -60,7 +61,7 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch() bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const { - return mFetchQueue.empty() && mBulkFetchCount<=0; + return mFetchQueue.empty() && mFetchCount<=0; } bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const @@ -98,19 +99,21 @@ bool LLInventoryModelBackgroundFetch::isEverythingFetched() const return mAllFoldersFetched; } -BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const +BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const { - return mBackgroundFetchActive; + return mFolderFetchActive; } -void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive) +void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) { - if (!mAllFoldersFetched || cat_id.notNull()) - { - LL_DEBUGS("InventoryFetch") << "Start fetching category: " << cat_id << ", recursive: " << recursive << LL_ENDL; + LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if (cat || (id.isNull() && !isEverythingFetched())) + { // it's a folder, do a bulk fetch + LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL; mBackgroundFetchActive = TRUE; - if (cat_id.isNull()) + mFolderFetchActive = true; + if (id.isNull()) { if (!mRecursiveInventoryFetchStarted) { @@ -128,41 +131,41 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive else { // Specific folder requests go to front of queue. - if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id) + if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id) { - mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive)); + mFetchQueue.push_front(FetchQueueInfo(id, recursive)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } - if (cat_id == gInventory.getLibraryRootFolderID()) + if (id == gInventory.getLibraryRootFolderID()) { mRecursiveLibraryFetchStarted |= recursive; } - if (cat_id == gInventory.getRootFolderID()) + if (id == gInventory.getRootFolderID()) { mRecursiveInventoryFetchStarted |= recursive; } } } + else if (LLViewerInventoryItem* itemp = gInventory.getItem(id)) + { + if (!itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)) + { + mBackgroundFetchActive = TRUE; + + mFetchQueue.push_front(FetchQueueInfo(id, false, false)); + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } + } } void LLInventoryModelBackgroundFetch::findLostItems() { mBackgroundFetchActive = TRUE; + mFolderFetchActive = true; mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } -void LLInventoryModelBackgroundFetch::stopBackgroundFetch() -{ - if (mBackgroundFetchActive) - { - mBackgroundFetchActive = FALSE; - gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); - mBulkFetchCount=0; - mMinTimeBetweenFetches=0.0f; - } -} - void LLInventoryModelBackgroundFetch::setAllFoldersFetched() { if (mRecursiveInventoryFetchStarted && @@ -170,7 +173,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() { mAllFoldersFetched = TRUE; } - stopBackgroundFetch(); + mFolderFetchActive = false; } void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *) @@ -183,10 +186,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() if (mBackgroundFetchActive && gAgent.getRegion()) { // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. - std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2"); - if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty()) + if (gSavedSettings.getBOOL("UseHTTPInventory")) { - bulkFetch(url); + bulkFetch(); return; } @@ -201,6 +203,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() llinfos << "Inventory fetch completed" << llendl; setAllFoldersFetched(); + mBackgroundFetchActive = false; + mFolderFetchActive = false; + return; } @@ -230,80 +235,114 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() } const FetchQueueInfo info = mFetchQueue.front(); - LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID); - // Category has been deleted, remove from queue. - if (!cat) + if (info.mIsCategory) { - mFetchQueue.pop_front(); - continue; - } + + LLViewerInventoryCategory* cat = gInventory.getCategory(info.mUUID); + + // Category has been deleted, remove from queue. + if (!cat) + { + mFetchQueue.pop_front(); + continue; + } - if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches && - LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) - { - // Category exists but has no children yet, fetch the descendants - // for now, just request every time and rely on retry timer to throttle. - if (cat->fetch()) + if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches && + LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) { - mFetchTimer.reset(); - mTimelyFetchPending = TRUE; + // Category exists but has no children yet, fetch the descendants + // for now, just request every time and rely on retry timer to throttle. + if (cat->fetch()) + { + mFetchTimer.reset(); + mTimelyFetchPending = TRUE; + } + else + { + // The catagory also tracks if it has expired and here it says it hasn't + // yet. Get out of here because nothing is going to happen until we + // update the timers. + break; + } } - else + // Do I have all my children? + else if (gInventory.isCategoryComplete(info.mUUID)) { - // The catagory also tracks if it has expired and here it says it hasn't - // yet. Get out of here because nothing is going to happen until we - // update the timers. + // Finished with this category, remove from queue. + mFetchQueue.pop_front(); + + // Add all children to queue. + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) + { + mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive)); + } + + // We received a response in less than the fast time. + if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time) + { + // Shrink timeouts based on success. + mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f); + mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f); + lldebugs << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl; + } + + mTimelyFetchPending = FALSE; + continue; + } + else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches) + { + // Received first packet, but our num descendants does not match db's num descendants + // so try again later. + mFetchQueue.pop_front(); + + if (mNumFetchRetries++ < MAX_FETCH_RETRIES) + { + // push on back of queue + mFetchQueue.push_back(info); + } + mTimelyFetchPending = FALSE; + mFetchTimer.reset(); break; } + + // Not enough time has elapsed to do a new fetch + break; } - // Do I have all my children? - else if (gInventory.isCategoryComplete(info.mCatUUID)) + else { - // Finished with this category, remove from queue. - mFetchQueue.pop_front(); + LLViewerInventoryItem* itemp = gInventory.getItem(info.mUUID); - // Add all children to queue. - LLInventoryModel::cat_array_t* categories; - LLInventoryModel::item_array_t* items; - gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); - for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); - it != categories->end(); - ++it) + mFetchQueue.pop_front(); + if (!itemp) { - mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive)); + continue; } - // We received a response in less than the fast time. - if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time) + if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches) { - // Shrink timeouts based on success. - mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f); - mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f); - lldebugs << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl; + itemp->fetchFromServer(); + mFetchTimer.reset(); + mTimelyFetchPending = TRUE; } - - mTimelyFetchPending = FALSE; - continue; - } - else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches) - { - // Received first packet, but our num descendants does not match db's num descendants - // so try again later. - mFetchQueue.pop_front(); - - if (mNumFetchRetries++ < MAX_FETCH_RETRIES) + else if (itemp->mIsComplete) + { + mTimelyFetchPending = FALSE; + } + else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches) { - // push on back of queue mFetchQueue.push_back(info); + mFetchTimer.reset(); + mTimelyFetchPending = FALSE; } - mTimelyFetchPending = FALSE; - mFetchTimer.reset(); + // Not enough time has elapsed to do a new fetch break; } - - // Not enough time has elapsed to do a new fetch - break; } // @@ -313,15 +352,35 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() } } -void LLInventoryModelBackgroundFetch::incrBulkFetch(S16 fetching) +void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching) { - mBulkFetchCount += fetching; - if (mBulkFetchCount < 0) + mFetchCount += fetching; + if (mFetchCount < 0) { - mBulkFetchCount = 0; + mFetchCount = 0; } } +class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder +{ +public: + LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {}; + void result(const LLSD& content); + void error(U32 status, const std::string& reason); +}; + +void LLInventoryModelFetchItemResponder::result( const LLSD& content ) +{ + LLInventoryModel::fetchInventoryResponder::result(content); + LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); +} + +void LLInventoryModelFetchItemResponder::error( U32 status, const std::string& reason ) +{ + LLInventoryModel::fetchInventoryResponder::error(status, reason); + LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); +} + class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder { @@ -458,7 +517,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) } } - fetcher->incrBulkFetch(-1); + fetcher->incrFetchCount(-1); if (fetcher->isBulkFetchProcessingComplete()) { @@ -477,7 +536,7 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str llinfos << "LLInventoryModelFetchDescendentsResponder::error " << status << ": " << reason << llendl; - fetcher->incrBulkFetch(-1); + fetcher->incrFetchCount(-1); if (status==499) // timed out { @@ -508,12 +567,13 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat // Bundle up a bunch of requests to send all at once. // static -void LLInventoryModelBackgroundFetch::bulkFetch(std::string url) +void LLInventoryModelBackgroundFetch::bulkFetch() { //Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. //If there are items in mFetchQueue, we want to check the time since the last bulkFetch was //sent. If it exceeds our retry time, go ahead and fire off another batch. - //Stopbackgroundfetch will be run from the Responder instead of here. + LLViewerRegion* region = gAgent.getRegion(); + if (!region) return; S16 max_concurrent_fetches=8; F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely. @@ -523,12 +583,13 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url) } if (gDisconnected || - (mBulkFetchCount > max_concurrent_fetches) || + (mFetchCount > max_concurrent_fetches) || (mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)) { return; // just bail if we are disconnected } + U32 item_count=0; U32 folder_count=0; U32 max_batch_size=5; @@ -536,83 +597,159 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url) uuid_vec_t recursive_cats; - LLSD body; - LLSD body_lib; + LLSD folder_request_body; + LLSD folder_request_body_lib; + LLSD item_request_body; + LLSD item_request_body_lib; - while (!(mFetchQueue.empty()) && (folder_count < max_batch_size)) + while (!mFetchQueue.empty() + && (item_count + folder_count) < max_batch_size) { const FetchQueueInfo& fetch_info = mFetchQueue.front(); - const LLUUID &cat_id = fetch_info.mCatUUID; - if (cat_id.isNull()) //DEV-17797 - { - LLSD folder_sd; - folder_sd["folder_id"] = LLUUID::null.asString(); - folder_sd["owner_id"] = gAgent.getID(); - folder_sd["sort_order"] = (LLSD::Integer)sort_order; - folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE; - folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; - body["folders"].append(folder_sd); - folder_count++; - } - else - { - const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + if (fetch_info.mIsCategory) + { + const LLUUID &cat_id = fetch_info.mUUID; + if (cat_id.isNull()) //DEV-17797 + { + LLSD folder_sd; + folder_sd["folder_id"] = LLUUID::null.asString(); + folder_sd["owner_id"] = gAgent.getID(); + folder_sd["sort_order"] = (LLSD::Integer)sort_order; + folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE; + folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; + folder_request_body["folders"].append(folder_sd); + folder_count++; + } + else + { + const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - if (cat) - { - if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) - { - LLSD folder_sd; - folder_sd["folder_id"] = cat->getUUID(); - folder_sd["owner_id"] = cat->getOwnerID(); - folder_sd["sort_order"] = (LLSD::Integer)sort_order; - folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted; - folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; - - if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) - body_lib["folders"].append(folder_sd); - else - body["folders"].append(folder_sd); - folder_count++; - } - // May already have this folder, but append child folders to list. - if (fetch_info.mRecursive) - { - LLInventoryModel::cat_array_t* categories; - LLInventoryModel::item_array_t* items; - gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); - for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); - it != categories->end(); - ++it) + if (cat) + { + if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) { - mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); - } - } - } - } - if (fetch_info.mRecursive) - recursive_cats.push_back(cat_id); + LLSD folder_sd; + folder_sd["folder_id"] = cat->getUUID(); + folder_sd["owner_id"] = cat->getOwnerID(); + folder_sd["sort_order"] = (LLSD::Integer)sort_order; + folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted; + folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; + + if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) + folder_request_body_lib["folders"].append(folder_sd); + else + folder_request_body["folders"].append(folder_sd); + folder_count++; + } + // May already have this folder, but append child folders to list. + if (fetch_info.mRecursive) + { + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) + { + mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + } + } + } + } + if (fetch_info.mRecursive) + recursive_cats.push_back(cat_id); + } + else + { + LLViewerInventoryItem* itemp = gInventory.getItem(fetch_info.mUUID); + if (itemp) + { + LLSD item_sd; + item_sd["owner_id"] = itemp->getPermissions().getOwner(); + item_sd["item_id"] = itemp->getUUID(); + if (itemp->getPermissions().getOwner() == gAgent.getID()) + { + item_request_body.append(item_sd); + } + else + { + item_request_body_lib.append(item_sd); + } + //itemp->fetchFromServer(); + item_count++; + } + } mFetchQueue.pop_front(); } - if (folder_count > 0) + if (item_count + folder_count > 0) { - mBulkFetchCount++; - if (body["folders"].size()) + if (folder_count) { - LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body, recursive_cats); - LLHTTPClient::post(url, body, fetcher, 300.0); + std::string url = region->getCapability("FetchInventoryDescendents2"); + mFetchCount++; + if (folder_request_body["folders"].size()) + { + LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats); + LLHTTPClient::post(url, folder_request_body, fetcher, 300.0); + } + if (folder_request_body_lib["folders"].size()) + { + std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2"); + + LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats); + LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0); + } } - if (body_lib["folders"].size()) + if (item_count) { - std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2"); - - LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats); - LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0); + std::string url; + + if (item_request_body.size()) + { + mFetchCount++; + url = region->getCapability("FetchInventory2"); + if (!url.empty()) + { + LLSD body; + body["agent_id"] = gAgent.getID(); + body["items"] = item_request_body; + + LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); + } + //else + //{ + // LLMessageSystem* msg = gMessageSystem; + // msg->newMessage("FetchInventory"); + // msg->nextBlock("AgentData"); + // msg->addUUID("AgentID", gAgent.getID()); + // msg->addUUID("SessionID", gAgent.getSessionID()); + // msg->nextBlock("InventoryData"); + // msg->addUUID("OwnerID", mPermissions.getOwner()); + // msg->addUUID("ItemID", mUUID); + // gAgent.sendReliableMessage(); + //} + } + + if (item_request_body_lib.size()) + { + mFetchCount++; + + url = region->getCapability("FetchLib2"); + if (!url.empty()) + { + LLSD body; + body["agent_id"] = gAgent.getID(); + body["items"] = item_request_body_lib; + + LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); + } + } } mFetchTimer.reset(); } + else if (isBulkFetchProcessingComplete()) { setAllFoldersFetched(); @@ -624,7 +761,7 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL for (fetch_queue_t::const_iterator it = mFetchQueue.begin(); it != mFetchQueue.end(); ++it) { - const LLUUID& fetch_id = (*it).mCatUUID; + const LLUUID& fetch_id = (*it).mUUID; if (gInventory.isObjectDescendentOf(fetch_id, cat_id)) return false; } diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index c35c785ceb..9dfedddd6d 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -48,7 +48,7 @@ public: // This gets triggered when performing a filter-search. void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE); - BOOL backgroundFetchActive() const; + BOOL folderFetchActive() const; bool isEverythingFetched() const; // completing the fetch once per session should be sufficient bool libraryFetchStarted() const; @@ -60,14 +60,13 @@ public: bool inventoryFetchInProgress() const; void findLostItems(); + void incrFetchCount(S16 fetching); protected: - void incrBulkFetch(S16 fetching); bool isBulkFetchProcessingComplete() const; - void bulkFetch(std::string url); + void bulkFetch(); void backgroundFetch(); static void backgroundFetchCB(void*); // background fetch idle function - void stopBackgroundFetch(); // stop fetch process void setAllFoldersFetched(); bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const; @@ -77,7 +76,8 @@ private: BOOL mAllFoldersFetched; BOOL mBackgroundFetchActive; - S16 mBulkFetchCount; + bool mFolderFetchActive; + S16 mFetchCount; BOOL mTimelyFetchPending; S32 mNumFetchRetries; @@ -87,11 +87,11 @@ private: struct FetchQueueInfo { - FetchQueueInfo(const LLUUID& id, BOOL recursive) : - mCatUUID(id), mRecursive(recursive) - { - } - LLUUID mCatUUID; + FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) : + mUUID(id), mRecursive(recursive), mIsCategory(is_category) + {} + LLUUID mUUID; + bool mIsCategory; BOOL mRecursive; }; typedef std::deque<FetchQueueInfo> fetch_queue_t; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 382569fa3a..71dd963f28 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -33,6 +33,7 @@ #include "llagentwearables.h" #include "llappearancemgr.h" #include "llavataractions.h" +#include "llclipboard.h" #include "llfloaterinventory.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" @@ -206,10 +207,11 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); LLScrollContainer::Params scroller_params(params.scroll()); scroller_params.rect(scroller_view_rect); - mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroller_params); + mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); addChild(mScroller); mScroller->addChild(mFolderRoot); mFolderRoot->setScrollContainer(mScroller); + mFolderRoot->setFollowsAll(); mFolderRoot->addChild(mFolderRoot->mStatusTextBox); } @@ -247,6 +249,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) getFilter()->setFilterEmptySystemFolders(); } + // keep track of the clipboard state so that we avoid filtering too much + mClipboardState = LLClipboard::instance().getGeneration(); + // Initialize base class params. LLPanel::initFromParams(params); } @@ -277,6 +282,14 @@ void LLInventoryPanel::draw() { // Select the desired item (in case it wasn't loaded when the selection was requested) mFolderRoot->updateSelection(); + + // Nudge the filter if the clipboard state changed + if (mClipboardState != LLClipboard::instance().getGeneration()) + { + mClipboardState = LLClipboard::instance().getGeneration(); + getFilter()->setModified(LLClipboard::instance().isCutMode() ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE : LLInventoryFilter::FILTER_LESS_RESTRICTIVE); + } + LLPanel::draw(); } @@ -817,7 +830,7 @@ BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask) if(handled) { ECursorType cursor = getWindow()->getCursor(); - if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && cursor == UI_CURSOR_ARROW) + if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() && cursor == UI_CURSOR_ARROW) { // replace arrow cursor with arrow and hourglass cursor getWindow()->setCursor(UI_CURSOR_WORKING); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 8279163762..6db59afb9b 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -160,6 +160,8 @@ public: void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); + LLHandle<LLInventoryPanel> getInventoryPanelHandle() const { return getDerivedHandle<LLInventoryPanel>(); } + // Callbacks void doToSelected(const LLSD& userdata); void doCreate(const LLSD& userdata); @@ -220,6 +222,7 @@ public: private: std::string mSortOrderSetting; + int mClipboardState; //-------------------------------------------------------------------- // Hidden folders diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp new file mode 100644 index 0000000000..459e52c4f4 --- /dev/null +++ b/indra/newview/lllocalbitmaps.cpp @@ -0,0 +1,942 @@ +/** + * @file lllocalbitmaps.cpp + * @author Vaalith Jinn + * @brief Local Bitmaps source + * + * $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$ + */ + +/* precompiled headers */ +#include "llviewerprecompiledheaders.h" + +/* own header */ +#include "lllocalbitmaps.h" + +/* boost: will not compile unless equivalent is undef'd, beware. */ +#ifdef equivalent +#undef equivalent +#endif +#include <boost/filesystem.hpp> + +/* image compression headers. */ +#include "llimagebmp.h" +#include "llimagetga.h" +#include "llimagejpeg.h" +#include "llimagepng.h" + +/* time headers */ +#include <time.h> +#include <ctime> + +/* misc headers */ +#include "llscrolllistctrl.h" +#include "llfilepicker.h" +#include "llviewertexturelist.h" +#include "llviewerobjectlist.h" +#include "llviewerobject.h" +#include "llface.h" +#include "llvoavatarself.h" +#include "llwearable.h" +#include "llagentwearables.h" +#include "lltexlayerparams.h" +#include "llvovolume.h" +#include "llnotificationsutil.h" + +/*=======================================*/ +/* Formal declarations, constants, etc. */ +/*=======================================*/ +std::list<LLLocalBitmap*> LLLocalBitmapMgr::sBitmapList; +LLLocalBitmapTimer LLLocalBitmapMgr::sTimer; +bool LLLocalBitmapMgr::sNeedsRebake; + +static const F32 LL_LOCAL_TIMER_HEARTBEAT = 3.0; +static const BOOL LL_LOCAL_USE_MIPMAPS = true; +static const S32 LL_LOCAL_DISCARD_LEVEL = 0; +static const U32 LL_LOCAL_TEXLAYER_FOR_IDX = 0; +static const bool LL_LOCAL_SLAM_FOR_DEBUG = true; +static const bool LL_LOCAL_REPLACE_ON_DEL = true; +static const S32 LL_LOCAL_UPDATE_RETRIES = 5; + +/*=======================================*/ +/* LLLocalBitmap: unit class */ +/*=======================================*/ +LLLocalBitmap::LLLocalBitmap(std::string filename) + : mFilename(filename) + , mShortName(gDirUtilp->getBaseFileName(filename, true)) + , mValid(false) + , mLastModified() + , mLinkStatus(LS_ON) + , mUpdateRetries(LL_LOCAL_UPDATE_RETRIES) +{ + mTrackingID.generate(); + + /* extension */ + std::string temp_exten = gDirUtilp->getExtension(mFilename); + + if (temp_exten == "bmp") + { + mExtension = ET_IMG_BMP; + } + else if (temp_exten == "tga") + { + mExtension = ET_IMG_TGA; + } + else if (temp_exten == "jpg" || temp_exten == "jpeg") + { + mExtension = ET_IMG_JPG; + } + else if (temp_exten == "png") + { + mExtension = ET_IMG_PNG; + } + else + { + llwarns << "File of no valid extension given, local bitmap creation aborted." << "\n" + << "Filename: " << mFilename << llendl; + return; // no valid extension. + } + + /* next phase of unit creation is nearly the same as an update cycle. + we're running updateSelf as a special case with the optional UT_FIRSTUSE + which omits the parts associated with removing the outdated texture */ + mValid = updateSelf(UT_FIRSTUSE); +} + +LLLocalBitmap::~LLLocalBitmap() +{ + // replace IDs with defaults, if set to do so. + if(LL_LOCAL_REPLACE_ON_DEL && mValid) // fix for STORM-1837 + { + replaceIDs(mWorldID, IMG_DEFAULT); + LLLocalBitmapMgr::doRebake(); + } + + // delete self from gimagelist + LLViewerFetchedTexture* image = gTextureList.findImage(mWorldID); + gTextureList.deleteImage(image); + + if (image) + { + image->unref(); + } +} + +/* accessors */ +std::string LLLocalBitmap::getFilename() +{ + return mFilename; +} + +std::string LLLocalBitmap::getShortName() +{ + return mShortName; +} + +LLUUID LLLocalBitmap::getTrackingID() +{ + return mTrackingID; +} + +LLUUID LLLocalBitmap::getWorldID() +{ + return mWorldID; +} + +bool LLLocalBitmap::getValid() +{ + return mValid; +} + +/* update functions */ +bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate) +{ + bool updated = false; + + if (mLinkStatus == LS_ON) + { + // verifying that the file exists + if (gDirUtilp->fileExists(mFilename)) + { + // verifying that the file has indeed been modified + const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename)); + LLSD new_last_modified = asctime(localtime(&temp_time)); + + if (mLastModified.asString() != new_last_modified.asString()) + { + /* loading the image file and decoding it, here is a critical point which, + if fails, invalidates the whole update (or unit creation) process. */ + LLPointer<LLImageRaw> raw_image = new LLImageRaw(); + if (decodeBitmap(raw_image)) + { + // decode is successful, we can safely proceed. + LLUUID old_id = LLUUID::null; + if (!(optional_firstupdate == UT_FIRSTUSE) && !mWorldID.isNull()) + { + old_id = mWorldID; + } + mWorldID.generate(); + mLastModified = new_last_modified; + + LLPointer<LLViewerFetchedTexture> texture = new LLViewerFetchedTexture + ("file://"+mFilename, mWorldID, LL_LOCAL_USE_MIPMAPS); + + texture->createGLTexture(LL_LOCAL_DISCARD_LEVEL, raw_image); + texture->setCachedRawImage(LL_LOCAL_DISCARD_LEVEL, raw_image); + texture->ref(); + + gTextureList.addImage(texture); + + if (!optional_firstupdate == UT_FIRSTUSE) + { + // seek out everything old_id uses and replace it with mWorldID + replaceIDs(old_id, mWorldID); + + // remove old_id from gimagelist + LLViewerFetchedTexture* image = gTextureList.findImage(old_id); + gTextureList.deleteImage(image); + image->unref(); + } + + mUpdateRetries = LL_LOCAL_UPDATE_RETRIES; + updated = true; + } + + // if decoding failed, we get here and it will attempt to decode it in the next cycles + // until mUpdateRetries runs out. this is done because some software lock the bitmap while writing to it + else + { + if (mUpdateRetries) + { + mUpdateRetries--; + } + else + { + llwarns << "During the update process the following file was found" << "\n" + << "but could not be opened or decoded for " << LL_LOCAL_UPDATE_RETRIES << " attempts." << "\n" + << "Filename: " << mFilename << "\n" + << "Disabling further update attempts for this file." << llendl; + + LLSD notif_args; + notif_args["FNAME"] = mFilename; + notif_args["NRETRIES"] = LL_LOCAL_UPDATE_RETRIES; + LLNotificationsUtil::add("LocalBitmapsUpdateFailedFinal", notif_args); + + mLinkStatus = LS_BROKEN; + } + } + } + + } // end if file exists + + else + { + llwarns << "During the update process, the following file was not found." << "\n" + << "Filename: " << mFilename << "\n" + << "Disabling further update attempts for this file." << llendl; + + LLSD notif_args; + notif_args["FNAME"] = mFilename; + LLNotificationsUtil::add("LocalBitmapsUpdateFileNotFound", notif_args); + + mLinkStatus = LS_BROKEN; + } + } + + return updated; +} + +bool LLLocalBitmap::decodeBitmap(LLPointer<LLImageRaw> rawimg) +{ + bool decode_successful = false; + + switch (mExtension) + { + case ET_IMG_BMP: + { + LLPointer<LLImageBMP> bmp_image = new LLImageBMP; + if (bmp_image->load(mFilename) && bmp_image->decode(rawimg, 0.0f)) + { + rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); + decode_successful = true; + } + break; + } + + case ET_IMG_TGA: + { + LLPointer<LLImageTGA> tga_image = new LLImageTGA; + if ((tga_image->load(mFilename) && tga_image->decode(rawimg)) + && ((tga_image->getComponents() == 3) || (tga_image->getComponents() == 4))) + { + rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); + decode_successful = true; + } + break; + } + + case ET_IMG_JPG: + { + LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG; + if (jpeg_image->load(mFilename) && jpeg_image->decode(rawimg, 0.0f)) + { + rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); + decode_successful = true; + } + break; + } + + case ET_IMG_PNG: + { + LLPointer<LLImagePNG> png_image = new LLImagePNG; + if (png_image->load(mFilename) && png_image->decode(rawimg, 0.0f)) + { + rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); + decode_successful = true; + } + break; + } + + default: + { + // separating this into -several- llwarns calls because in the extremely unlikely case that this happens + // accessing mFilename and any other object properties might very well crash the viewer. + // getting here should be impossible, or there's been a pretty serious bug. + + llwarns << "During a decode attempt, the following local bitmap had no properly assigned extension." << llendl; + llwarns << "Filename: " << mFilename << llendl; + llwarns << "Disabling further update attempts for this file." << llendl; + mLinkStatus = LS_BROKEN; + } + } + + return decode_successful; +} + +void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id) +{ + // checking for misuse. + if (old_id == new_id) + { + llinfos << "An attempt was made to replace a texture with itself. (matching UUIDs)" << "\n" + << "Texture UUID: " << old_id.asString() << llendl; + return; + } + + updateUserPrims(old_id, new_id); + updateUserSculpts(old_id, new_id); // isn't there supposed to be an IMG_DEFAULT_SCULPT or something? + + // default safeguard image for layers + if( new_id == IMG_DEFAULT ) + { + new_id = IMG_DEFAULT_AVATAR; + } + + /* It doesn't actually update all of those, it merely checks if any of them + contain the referenced ID and if so, updates. */ + updateUserLayers(old_id, new_id, LLWearableType::WT_ALPHA); + updateUserLayers(old_id, new_id, LLWearableType::WT_EYES); + updateUserLayers(old_id, new_id, LLWearableType::WT_GLOVES); + updateUserLayers(old_id, new_id, LLWearableType::WT_JACKET); + updateUserLayers(old_id, new_id, LLWearableType::WT_PANTS); + updateUserLayers(old_id, new_id, LLWearableType::WT_SHIRT); + updateUserLayers(old_id, new_id, LLWearableType::WT_SHOES); + updateUserLayers(old_id, new_id, LLWearableType::WT_SKIN); + updateUserLayers(old_id, new_id, LLWearableType::WT_SKIRT); + updateUserLayers(old_id, new_id, LLWearableType::WT_SOCKS); + updateUserLayers(old_id, new_id, LLWearableType::WT_TATTOO); + updateUserLayers(old_id, new_id, LLWearableType::WT_UNDERPANTS); + updateUserLayers(old_id, new_id, LLWearableType::WT_UNDERSHIRT); +} + +// this function sorts the faces from a getFaceList[getNumFaces] into a list of objects +// in order to prevent multiple sendTEUpdate calls per object during updateUserPrims +std::vector<LLViewerObject*> LLLocalBitmap::prepUpdateObjects(LLUUID old_id) +{ + std::vector<LLViewerObject*> obj_list; + LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id); + + for(U32 face_iterator = 0; face_iterator < old_texture->getNumFaces(); face_iterator++) + { + // getting an object from a face + LLFace* face_to_object = (*old_texture->getFaceList())[face_iterator]; + + if(face_to_object) + { + LLViewerObject* affected_object = face_to_object->getViewerObject(); + + if(affected_object) + { + + // we have an object, we'll take it's UUID and compare it to + // whatever we already have in the returnable object list. + // if there is a match - we do not add (to prevent duplicates) + LLUUID mainlist_obj_id = affected_object->getID(); + bool add_object = true; + + // begin looking for duplicates + std::vector<LLViewerObject*>::iterator objlist_iter = obj_list.begin(); + for(; (objlist_iter != obj_list.end()) && add_object; objlist_iter++) + { + LLViewerObject* obj = *objlist_iter; + if (obj->getID() == mainlist_obj_id) + { + add_object = false; // duplicate found. + } + } + // end looking for duplicates + + if(add_object) + { + obj_list.push_back(affected_object); + } + + } + + } + + } // end of face-iterating for() + + return obj_list; +} + +void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id) +{ + std::vector<LLViewerObject*> objectlist = prepUpdateObjects(old_id); + + for(std::vector<LLViewerObject*>::iterator object_iterator = objectlist.begin(); + object_iterator != objectlist.end(); object_iterator++) + { + LLViewerObject* object = *object_iterator; + + if(object) + { + bool update_obj = false; + S32 num_faces = object->getNumFaces(); + + for (U8 face_iter = 0; face_iter < num_faces; face_iter++) + { + if (object->mDrawable) + { + LLFace* face = object->mDrawable->getFace(face_iter); + if (face && face->getTexture() && face->getTexture()->getID() == old_id) + { + object->setTEImage(face_iter, LLViewerTextureManager::getFetchedTexture + (new_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + + update_obj = true; + } + } + } + + if (update_obj) + { + object->sendTEUpdate(); + } + } + } + +} + +void LLLocalBitmap::updateUserSculpts(LLUUID old_id, LLUUID new_id) +{ + LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id); + for(U32 volume_iter = 0; volume_iter < old_texture->getNumVolumes(); volume_iter++) + { + LLVOVolume* volume_to_object = (*old_texture->getVolumeList())[volume_iter]; + LLViewerObject* object = (LLViewerObject*)volume_to_object; + + if(object) + { + if (object->isSculpted() && object->getVolume() && + object->getVolume()->getParams().getSculptID() == old_id) + { + LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams new_params(*old_params); + new_params.setSculptTexture(new_id); + object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, TRUE); + } + } + } +} + +void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type) +{ + U32 count = gAgentWearables.getWearableCount(type); + for(U32 wearable_iter = 0; wearable_iter < count; wearable_iter++) + { + LLWearable* wearable = gAgentWearables.getWearable(type, wearable_iter); + if (wearable) + { + std::vector<LLLocalTextureObject*> texture_list = wearable->getLocalTextureListSeq(); + for(std::vector<LLLocalTextureObject*>::iterator texture_iter = texture_list.begin(); + texture_iter != texture_list.end(); texture_iter++) + { + LLLocalTextureObject* lto = *texture_iter; + + if (lto && lto->getID() == old_id) + { + U32 local_texlayer_index = 0; /* can't keep that as static const, gives errors, so i'm leaving this var here */ + LLVOAvatarDefines::EBakedTextureIndex baked_texind = + lto->getTexLayer(local_texlayer_index)->getTexLayerSet()->getBakedTexIndex(); + + LLVOAvatarDefines::ETextureIndex reg_texind = getTexIndex(type, baked_texind); + if (reg_texind != LLVOAvatarDefines::TEX_NUM_INDICES) + { + U32 index = gAgentWearables.getWearableIndex(wearable); + gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index); + gAgentAvatarp->wearableUpdated(type, FALSE); + + /* telling the manager to rebake once update cycle is fully done */ + LLLocalBitmapMgr::setNeedsRebake(); + } + + } + } + } + } +} + +LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( + LLWearableType::EType type, LLVOAvatarDefines::EBakedTextureIndex baked_texind) +{ + LLVOAvatarDefines::ETextureIndex result = LLVOAvatarDefines::TEX_NUM_INDICES; // using as a default/fail return. + + switch(type) + { + case LLWearableType::WT_ALPHA: + { + switch(baked_texind) + { + case LLVOAvatarDefines::BAKED_EYES: + { + result = LLVOAvatarDefines::TEX_EYES_ALPHA; + break; + } + + case LLVOAvatarDefines::BAKED_HAIR: + { + result = LLVOAvatarDefines::TEX_HAIR_ALPHA; + break; + } + + case LLVOAvatarDefines::BAKED_HEAD: + { + result = LLVOAvatarDefines::TEX_HEAD_ALPHA; + break; + } + + case LLVOAvatarDefines::BAKED_LOWER: + { + result = LLVOAvatarDefines::TEX_LOWER_ALPHA; + break; + } + case LLVOAvatarDefines::BAKED_UPPER: + { + result = LLVOAvatarDefines::TEX_UPPER_ALPHA; + break; + } + + default: + { + break; + } + + } + break; + + } + + case LLWearableType::WT_EYES: + { + if (baked_texind == LLVOAvatarDefines::BAKED_EYES) + { + result = LLVOAvatarDefines::TEX_EYES_IRIS; + } + + break; + } + + case LLWearableType::WT_GLOVES: + { + if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + { + result = LLVOAvatarDefines::TEX_UPPER_GLOVES; + } + + break; + } + + case LLWearableType::WT_JACKET: + { + if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + { + result = LLVOAvatarDefines::TEX_LOWER_JACKET; + } + else if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + { + result = LLVOAvatarDefines::TEX_UPPER_JACKET; + } + + break; + } + + case LLWearableType::WT_PANTS: + { + if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + { + result = LLVOAvatarDefines::TEX_LOWER_PANTS; + } + + break; + } + + case LLWearableType::WT_SHIRT: + { + if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + { + result = LLVOAvatarDefines::TEX_UPPER_SHIRT; + } + + break; + } + + case LLWearableType::WT_SHOES: + { + if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + { + result = LLVOAvatarDefines::TEX_LOWER_SHOES; + } + + break; + } + + case LLWearableType::WT_SKIN: + { + switch(baked_texind) + { + case LLVOAvatarDefines::BAKED_HEAD: + { + result = LLVOAvatarDefines::TEX_HEAD_BODYPAINT; + break; + } + + case LLVOAvatarDefines::BAKED_LOWER: + { + result = LLVOAvatarDefines::TEX_LOWER_BODYPAINT; + break; + } + case LLVOAvatarDefines::BAKED_UPPER: + { + result = LLVOAvatarDefines::TEX_UPPER_BODYPAINT; + break; + } + + default: + { + break; + } + + } + break; + } + + case LLWearableType::WT_SKIRT: + { + if (baked_texind == LLVOAvatarDefines::BAKED_SKIRT) + { + result = LLVOAvatarDefines::TEX_SKIRT; + } + + break; + } + + case LLWearableType::WT_SOCKS: + { + if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + { + result = LLVOAvatarDefines::TEX_LOWER_SOCKS; + } + + break; + } + + case LLWearableType::WT_TATTOO: + { + switch(baked_texind) + { + case LLVOAvatarDefines::BAKED_HEAD: + { + result = LLVOAvatarDefines::TEX_HEAD_TATTOO; + break; + } + + case LLVOAvatarDefines::BAKED_LOWER: + { + result = LLVOAvatarDefines::TEX_LOWER_TATTOO; + break; + } + case LLVOAvatarDefines::BAKED_UPPER: + { + result = LLVOAvatarDefines::TEX_UPPER_TATTOO; + break; + } + + default: + { + break; + } + + } + break; + } + + case LLWearableType::WT_UNDERPANTS: + { + if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + { + result = LLVOAvatarDefines::TEX_LOWER_UNDERPANTS; + } + + break; + } + + case LLWearableType::WT_UNDERSHIRT: + { + if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + { + result = LLVOAvatarDefines::TEX_UPPER_UNDERSHIRT; + } + + break; + } + + default: + { + llwarns << "Unknown wearable type: " << (int)type << "\n" + << "Baked Texture Index: " << (int)baked_texind << "\n" + << "Filename: " << mFilename << "\n" + << "TrackingID: " << mTrackingID << "\n" + << "InworldID: " << mWorldID << llendl; + } + + } + return result; +} + +/*=======================================*/ +/* LLLocalBitmapTimer: timer class */ +/*=======================================*/ +LLLocalBitmapTimer::LLLocalBitmapTimer() : LLEventTimer(LL_LOCAL_TIMER_HEARTBEAT) +{ +} + +LLLocalBitmapTimer::~LLLocalBitmapTimer() +{ +} + +void LLLocalBitmapTimer::startTimer() +{ + mEventTimer.start(); +} + +void LLLocalBitmapTimer::stopTimer() +{ + mEventTimer.stop(); +} + +bool LLLocalBitmapTimer::isRunning() +{ + return mEventTimer.getStarted(); +} + +BOOL LLLocalBitmapTimer::tick() +{ + LLLocalBitmapMgr::doUpdates(); + return FALSE; +} + +/*=======================================*/ +/* LLLocalBitmapMgr: manager class */ +/*=======================================*/ +LLLocalBitmapMgr::LLLocalBitmapMgr() +{ + // The class is all made of static members, should i even bother instantiating? +} + +LLLocalBitmapMgr::~LLLocalBitmapMgr() +{ +} + +bool LLLocalBitmapMgr::addUnit() +{ + bool add_successful = false; + + LLFilePicker& picker = LLFilePicker::instance(); + if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE)) + { + sTimer.stopTimer(); + + std::string filename = picker.getFirstFile(); + while(!filename.empty()) + { + LLLocalBitmap* unit = new LLLocalBitmap(filename); + + if (unit->getValid()) + { + sBitmapList.push_back(unit); + add_successful = true; + } + else + { + llwarns << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" + << "Filename: " << filename << llendl; + + LLSD notif_args; + notif_args["FNAME"] = filename; + LLNotificationsUtil::add("LocalBitmapsVerifyFail", notif_args); + + delete unit; + unit = NULL; + } + + filename = picker.getNextFile(); + } + + sTimer.startTimer(); + } + + return add_successful; +} + +void LLLocalBitmapMgr::delUnit(LLUUID tracking_id) +{ + if (!sBitmapList.empty()) + { + std::vector<LLLocalBitmap*> to_delete; + for (local_list_iter iter = sBitmapList.begin(); iter != sBitmapList.end(); iter++) + { /* finding which ones we want deleted and making a separate list */ + LLLocalBitmap* unit = *iter; + if (unit->getTrackingID() == tracking_id) + { + to_delete.push_back(unit); + } + } + + for(std::vector<LLLocalBitmap*>::iterator del_iter = to_delete.begin(); + del_iter != to_delete.end(); del_iter++) + { /* iterating over a temporary list, hence preserving the iterator validity while deleting. */ + LLLocalBitmap* unit = *del_iter; + sBitmapList.remove(unit); + delete unit; + unit = NULL; + } + } +} + +LLUUID LLLocalBitmapMgr::getWorldID(LLUUID tracking_id) +{ + LLUUID world_id = LLUUID::null; + + for (local_list_iter iter = sBitmapList.begin(); iter != sBitmapList.end(); iter++) + { + LLLocalBitmap* unit = *iter; + if (unit->getTrackingID() == tracking_id) + { + world_id = unit->getWorldID(); + } + } + + return world_id; +} + +std::string LLLocalBitmapMgr::getFilename(LLUUID tracking_id) +{ + std::string filename = ""; + + for (local_list_iter iter = sBitmapList.begin(); iter != sBitmapList.end(); iter++) + { + LLLocalBitmap* unit = *iter; + if (unit->getTrackingID() == tracking_id) + { + filename = unit->getFilename(); + } + } + + return filename; +} + +void LLLocalBitmapMgr::feedScrollList(LLScrollListCtrl* ctrl) +{ + if (ctrl) + { + ctrl->clearRows(); + + if (!sBitmapList.empty()) + { + for (local_list_iter iter = sBitmapList.begin(); + iter != sBitmapList.end(); iter++) + { + LLSD element; + element["columns"][0]["column"] = "unit_name"; + element["columns"][0]["type"] = "text"; + element["columns"][0]["value"] = (*iter)->getShortName(); + + element["columns"][1]["column"] = "unit_id_HIDDEN"; + element["columns"][1]["type"] = "text"; + element["columns"][1]["value"] = (*iter)->getTrackingID(); + + ctrl->addElement(element); + } + } + } + +} + +void LLLocalBitmapMgr::doUpdates() +{ + // preventing theoretical overlap in cases with huge number of loaded images. + sTimer.stopTimer(); + sNeedsRebake = false; + + for (local_list_iter iter = sBitmapList.begin(); iter != sBitmapList.end(); iter++) + { + (*iter)->updateSelf(); + } + + doRebake(); + sTimer.startTimer(); +} + +void LLLocalBitmapMgr::setNeedsRebake() +{ + sNeedsRebake = true; +} + +void LLLocalBitmapMgr::doRebake() +{ /* separated that from doUpdates to insure a rebake can be called separately during deletion */ + if (sNeedsRebake) + { + gAgentAvatarp->forceBakeAllTextures(LL_LOCAL_SLAM_FOR_DEBUG); + sNeedsRebake = false; + } +} + diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h new file mode 100644 index 0000000000..7a23c7ef6e --- /dev/null +++ b/indra/newview/lllocalbitmaps.h @@ -0,0 +1,136 @@ +/** + * @file lllocalbitmaps.h + * @author Vaalith Jinn + * @brief Local Bitmaps header + * + * $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$ + */ + +#ifndef LL_LOCALBITMAPS_H +#define LL_LOCALBITMAPS_H + +#include "lleventtimer.h" +#include "llwearabletype.h" +#include "llvoavatardefines.h" + +class LLScrollListCtrl; + +class LLLocalBitmap +{ + public: /* main */ + LLLocalBitmap(std::string filename); + ~LLLocalBitmap(); + + public: /* accessors */ + std::string getFilename(); + std::string getShortName(); + LLUUID getTrackingID(); + LLUUID getWorldID(); + bool getValid(); + + public: /* self update public section */ + enum EUpdateType + { + UT_FIRSTUSE, + UT_REGUPDATE + }; + + bool updateSelf(EUpdateType = UT_REGUPDATE); + + private: /* self update private section */ + bool decodeBitmap(LLPointer<LLImageRaw> raw); + void replaceIDs(LLUUID old_id, LLUUID new_id); + std::vector<LLViewerObject*> prepUpdateObjects(LLUUID old_id); + void updateUserPrims(LLUUID old_id, LLUUID new_id); + void updateUserSculpts(LLUUID old_id, LLUUID new_id); + void updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type); + LLVOAvatarDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLVOAvatarDefines::EBakedTextureIndex baked_texind); + + private: /* private enums */ + enum ELinkStatus + { + LS_ON, + LS_BROKEN, + }; + + enum EExtension + { + ET_IMG_BMP, + ET_IMG_TGA, + ET_IMG_JPG, + ET_IMG_PNG + }; + + private: /* members */ + std::string mFilename; + std::string mShortName; + LLUUID mTrackingID; + LLUUID mWorldID; + bool mValid; + LLSD mLastModified; + EExtension mExtension; + ELinkStatus mLinkStatus; + S32 mUpdateRetries; + +}; + +class LLLocalBitmapTimer : public LLEventTimer +{ + public: + LLLocalBitmapTimer(); + ~LLLocalBitmapTimer(); + + public: + void startTimer(); + void stopTimer(); + bool isRunning(); + BOOL tick(); + +}; + +class LLLocalBitmapMgr +{ + public: + LLLocalBitmapMgr(); + ~LLLocalBitmapMgr(); + + public: + static bool addUnit(); + static void delUnit(LLUUID tracking_id); + + static LLUUID getWorldID(LLUUID tracking_id); + static std::string getFilename(LLUUID tracking_id); + + static void feedScrollList(LLScrollListCtrl* ctrl); + static void doUpdates(); + static void setNeedsRebake(); + static void doRebake(); + + private: + static std::list<LLLocalBitmap*> sBitmapList; + static LLLocalBitmapTimer sTimer; + static bool sNeedsRebake; + typedef std::list<LLLocalBitmap*>::iterator local_list_iter; +}; + +#endif + diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index a3f0a6062c..93dd82957f 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -30,6 +30,7 @@ #include "llagent.h" #include "llhttpclient.h" +#include "lltimer.h" #include "lltrans.h" #include "llviewercontrol.h" #include "llviewermedia.h" @@ -115,6 +116,9 @@ namespace LLMarketplaceImport static U32 sImportResultStatus = 0; static LLSD sImportResults = LLSD::emptyMap(); + static LLTimer slmGetTimer; + static LLTimer slmPostTimer; + // Responders class LLImportPostResponder : public LLHTTPClient::Responder @@ -124,11 +128,15 @@ namespace LLMarketplaceImport void completed(U32 status, const std::string& reason, const LLSD& content) { + slmPostTimer.stop(); + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { llinfos << " SLM POST status: " << status << llendl; llinfos << " SLM POST reason: " << reason << llendl; llinfos << " SLM POST content: " << content.asString() << llendl; + + llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl; } if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) || @@ -167,11 +175,15 @@ namespace LLMarketplaceImport void completed(U32 status, const std::string& reason, const LLSD& content) { + slmGetTimer.stop(); + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { llinfos << " SLM GET status: " << status << llendl; llinfos << " SLM GET reason: " << reason << llendl; llinfos << " SLM GET content: " << content.asString() << llendl; + + llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl; } if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || @@ -247,6 +259,7 @@ namespace LLMarketplaceImport llinfos << " SLM GET: " << url << llendl; } + slmGetTimer.start(); LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders()); return true; @@ -277,6 +290,7 @@ namespace LLMarketplaceImport llinfos << " SLM GET: " << url << llendl; } + slmGetTimer.start(); LLHTTPClient::get(url, new LLImportGetResponder(), headers); return true; @@ -310,6 +324,7 @@ namespace LLMarketplaceImport llinfos << " SLM POST: " << url << llendl; } + slmPostTimer.start(); LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers); return true; diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp index 7e9c3c84a7..c0a323d6cb 100644 --- a/indra/newview/llmemoryview.cpp +++ b/indra/newview/llmemoryview.cpp @@ -220,7 +220,7 @@ void LLMemoryView::draw() S32 x, y; S32 margin = 10; - S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); + S32 texth = LLFontGL::getFontMonospace()->getLineHeight(); S32 xleft = margin; S32 ytop = height - margin; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index b02bf79a28..c899e8991e 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -508,6 +508,7 @@ void LLMeshRepoThread::run() while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveLODRequests < sMaxConcurrentRequests) { + if (mMutex) { mMutex->lock(); LODRequest req = mLODReqQ.front(); @@ -525,6 +526,7 @@ void LLMeshRepoThread::run() while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveHeaderRequests < sMaxConcurrentRequests) { + if (mMutex) { mMutex->lock(); HeaderRequest req = mHeaderReqQ.front(); @@ -671,6 +673,12 @@ std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id) bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) { //protected by mMutex + + if (!mHeaderMutex) + { + return false; + } + mHeaderMutex->lock(); if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) @@ -728,7 +736,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) if (!http_url.empty()) { ret = mCurlRequest->getByteRange(http_url, headers, offset, size, - new LLMeshSkinInfoResponder(mesh_id, offset, size)); + new LLMeshSkinInfoResponder(mesh_id, offset, size)); if(ret) { LLMeshRepository::sHTTPRequestCount++; @@ -747,6 +755,11 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) { //protected by mMutex + if (!mHeaderMutex) + { + return false; + } + mHeaderMutex->lock(); if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) @@ -805,7 +818,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) if (!http_url.empty()) { ret = mCurlRequest->getByteRange(http_url, headers, offset, size, - new LLMeshDecompositionResponder(mesh_id, offset, size)); + new LLMeshDecompositionResponder(mesh_id, offset, size)); if(ret) { LLMeshRepository::sHTTPRequestCount++; @@ -824,6 +837,11 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) { //protected by mMutex + if (!mHeaderMutex) + { + return false; + } + mHeaderMutex->lock(); if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) @@ -881,7 +899,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) if (!http_url.empty()) { ret = mCurlRequest->getByteRange(http_url, headers, offset, size, - new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); + new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); if(ret) { @@ -950,6 +968,11 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c //return false if failed to get mesh lod. bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count) { //protected by mMutex + if (!mHeaderMutex) + { + return false; + } + mHeaderMutex->lock(); bool retval = true; @@ -1068,10 +1091,11 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat { LLUUID mesh_id = mesh_params.getSculptID(); - mHeaderMutex->lock(); - mMeshHeaderSize[mesh_id] = header_size; - mMeshHeader[mesh_id] = header; - mHeaderMutex->unlock(); + { + LLMutexLock lock(mHeaderMutex); + mMeshHeaderSize[mesh_id] = header_size; + mMeshHeader[mesh_id] = header; + } //check for pending requests pending_lod_map::iterator iter = mPendingLOD.find(mesh_params); @@ -1093,17 +1117,19 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size) { - LLVolume* volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); + LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); std::string mesh_string((char*) data, data_size); std::istringstream stream(mesh_string); if (volume->unpackVolumeFaces(stream, data_size)) { - LoadedMesh mesh(volume, mesh_params, lod); if (volume->getNumFaces() > 0) { - LLMutexLock lock(mMutex); - mLoadedQ.push(mesh); + LoadedMesh mesh(volume, mesh_params, lod); + { + LLMutexLock lock(mMutex); + mLoadedQ.push(mesh); + } return true; } } @@ -1594,7 +1620,7 @@ void LLMeshUploadThread::doWholeModelUpload() mCurlRequest->process(); //sleep for 10ms to prevent eating a whole core apr_sleep(10000); - } while (mCurlRequest->getQueued() > 0); + } while (!LLAppViewer::isQuitting() && mCurlRequest->getQueued() > 0); } delete mCurlRequest; @@ -1644,6 +1670,11 @@ void LLMeshUploadThread::requestWholeModelFee() void LLMeshRepoThread::notifyLoadedMeshes() { + if (!mMutex) + { + return; + } + while (!mLoadedQ.empty()) { mMutex->lock(); @@ -2355,93 +2386,92 @@ void LLMeshRepository::notifyLoadedMeshes() } } - mMeshMutex->lock(); - mThread->mMutex->lock(); - - //popup queued error messages from background threads - while (!mUploadErrorQ.empty()) { - LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front()); - mUploadErrorQ.pop(); - } + LLMutexLock lock1(mMeshMutex); + LLMutexLock lock2(mThread->mMutex); + + //popup queued error messages from background threads + while (!mUploadErrorQ.empty()) + { + LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front()); + mUploadErrorQ.pop(); + } - S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests); + S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests); - if (push_count > 0) - { - //calculate "score" for pending requests + if (push_count > 0) + { + //calculate "score" for pending requests - //create score map - std::map<LLUUID, F32> score_map; + //create score map + std::map<LLUUID, F32> score_map; - for (U32 i = 0; i < 4; ++i) - { - for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) + for (U32 i = 0; i < 4; ++i) { - F32 max_score = 0.f; - for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) + for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) { - LLViewerObject* object = gObjectList.findObject(*obj_iter); - - if (object) + F32 max_score = 0.f; + for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) { - LLDrawable* drawable = object->mDrawable; - if (drawable) + LLViewerObject* object = gObjectList.findObject(*obj_iter); + + if (object) { - F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f); - max_score = llmax(max_score, cur_score); + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f); + max_score = llmax(max_score, cur_score); + } } } - } - score_map[iter->first.getSculptID()] = max_score; + score_map[iter->first.getSculptID()] = max_score; + } + } + + //set "score" for pending requests + for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter) + { + iter->mScore = score_map[iter->mMeshParams.getSculptID()]; + } + + //sort by "score" + std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); + + while (!mPendingRequests.empty() && push_count > 0) + { + LLMeshRepoThread::LODRequest& request = mPendingRequests.front(); + mThread->loadMeshLOD(request.mMeshParams, request.mLOD); + mPendingRequests.erase(mPendingRequests.begin()); + LLMeshRepository::sLODPending--; + push_count--; } } - //set "score" for pending requests - for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter) + //send skin info requests + while (!mPendingSkinRequests.empty()) { - iter->mScore = score_map[iter->mMeshParams.getSculptID()]; + mThread->loadMeshSkinInfo(mPendingSkinRequests.front()); + mPendingSkinRequests.pop(); } - - //sort by "score" - std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); - - while (!mPendingRequests.empty() && push_count > 0) + + //send decomposition requests + while (!mPendingDecompositionRequests.empty()) { - LLMeshRepoThread::LODRequest& request = mPendingRequests.front(); - mThread->loadMeshLOD(request.mMeshParams, request.mLOD); - mPendingRequests.erase(mPendingRequests.begin()); - LLMeshRepository::sLODPending--; - push_count--; + mThread->loadMeshDecomposition(mPendingDecompositionRequests.front()); + mPendingDecompositionRequests.pop(); } - } - - //send skin info requests - while (!mPendingSkinRequests.empty()) - { - mThread->loadMeshSkinInfo(mPendingSkinRequests.front()); - mPendingSkinRequests.pop(); - } - //send decomposition requests - while (!mPendingDecompositionRequests.empty()) - { - mThread->loadMeshDecomposition(mPendingDecompositionRequests.front()); - mPendingDecompositionRequests.pop(); - } + //send physics shapes decomposition requests + while (!mPendingPhysicsShapeRequests.empty()) + { + mThread->loadMeshPhysicsShape(mPendingPhysicsShapeRequests.front()); + mPendingPhysicsShapeRequests.pop(); + } - //send physics shapes decomposition requests - while (!mPendingPhysicsShapeRequests.empty()) - { - mThread->loadMeshPhysicsShape(mPendingPhysicsShapeRequests.front()); - mPendingPhysicsShapeRequests.pop(); + mThread->notifyLoadedMeshes(); } - - mThread->notifyLoadedMeshes(); - - mThread->mMutex->unlock(); - mMeshMutex->unlock(); mThread->mSignal->signal(); } @@ -3089,13 +3119,14 @@ void LLPhysicsDecomp::doDecomposition() num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(stage); } - mMutex->lock(); - mCurRequest->mHull.clear(); - mCurRequest->mHull.resize(num_hulls); + { + LLMutexLock lock(mMutex); + mCurRequest->mHull.clear(); + mCurRequest->mHull.resize(num_hulls); - mCurRequest->mHullMesh.clear(); - mCurRequest->mHullMesh.resize(num_hulls); - mMutex->unlock(); + mCurRequest->mHullMesh.clear(); + mCurRequest->mHullMesh.resize(num_hulls); + } for (S32 i = 0; i < num_hulls; ++i) { @@ -3119,14 +3150,14 @@ void LLPhysicsDecomp::doDecomposition() get_vertex_buffer_from_mesh(mesh, mCurRequest->mHullMesh[i]); - mMutex->lock(); - mCurRequest->mHull[i] = p; - mMutex->unlock(); + { + LLMutexLock lock(mMutex); + mCurRequest->mHull[i] = p; + } } { LLMutexLock lock(mMutex); - mCurRequest->setStatusMessage("FAIL"); completeCurrent(); } @@ -3194,7 +3225,6 @@ void LLPhysicsDecomp::doDecompositionSingleHull() LLCDMeshData mesh; -#if 1 setMeshData(mesh, true); LLCDResult ret = decomp->buildSingleHull() ; @@ -3205,11 +3235,12 @@ void LLPhysicsDecomp::doDecompositionSingleHull() } else { - mMutex->lock(); - mCurRequest->mHull.clear(); - mCurRequest->mHull.resize(1); - mCurRequest->mHullMesh.clear(); - mMutex->unlock(); + { + LLMutexLock lock(mMutex); + mCurRequest->mHull.clear(); + mCurRequest->mHull.resize(1); + mCurRequest->mHullMesh.clear(); + } std::vector<LLVector3> p; LLCDHull hull; @@ -3225,93 +3256,12 @@ void LLPhysicsDecomp::doDecompositionSingleHull() p.push_back(vert); v = (F32*) (((U8*) v) + hull.mVertexStrideBytes); } - - mMutex->lock(); - mCurRequest->mHull[0] = p; - mMutex->unlock(); - } -#else - setMeshData(mesh, false); - - //set all parameters to default - std::map<std::string, const LLCDParam*> param_map; - - static const LLCDParam* params = NULL; - static S32 param_count = 0; - - if (!params) - { - param_count = decomp->getParameters(¶ms); - } - - for (S32 i = 0; i < param_count; ++i) - { - decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue); - } - - const S32 STAGE_DECOMPOSE = mStageID["Decompose"]; - const S32 STAGE_SIMPLIFY = mStageID["Simplify"]; - const S32 DECOMP_PREVIEW = 0; - const S32 SIMPLIFY_RETAIN = 0; - - decomp->setParam("Decompose Quality", DECOMP_PREVIEW); - decomp->setParam("Simplify Method", SIMPLIFY_RETAIN); - decomp->setParam("Retain%", 0.f); - - LLCDResult ret = LLCD_OK; - ret = decomp->executeStage(STAGE_DECOMPOSE); - - if (ret) - { - llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl; - make_box(mCurRequest); - } - else - { - ret = decomp->executeStage(STAGE_SIMPLIFY); - - if (ret) - { - llwarns << "Could not execute simiplification stage when attempting to create single hull." << llendl; - make_box(mCurRequest); - } - else + { - S32 num_hulls =0; - if (LLConvexDecomposition::getInstance() != NULL) - { - num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(STAGE_SIMPLIFY); - } - - mMutex->lock(); - mCurRequest->mHull.clear(); - mCurRequest->mHull.resize(num_hulls); - mCurRequest->mHullMesh.clear(); - mMutex->unlock(); - - for (S32 i = 0; i < num_hulls; ++i) - { - std::vector<LLVector3> p; - LLCDHull hull; - // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code - LLConvexDecomposition::getInstance()->getHullFromStage(STAGE_SIMPLIFY, i, &hull); - - const F32* v = hull.mVertexBase; - - for (S32 j = 0; j < hull.mNumVertices; ++j) - { - LLVector3 vert(v[0], v[1], v[2]); - p.push_back(vert); - v = (F32*) (((U8*) v) + hull.mVertexStrideBytes); - } - - mMutex->lock(); - mCurRequest->mHull[i] = p; - mMutex->unlock(); - } + LLMutexLock lock(mMutex); + mCurRequest->mHull[0] = p; } - } -#endif + } { completeCurrent(); diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 04e1570081..7a70370fe3 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -29,6 +29,7 @@ #include "llstring.h" #include "lluuid.h" +#include "llextendedstatus.h" class LLViewerObject; class LLMessageSystem; diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 2a08cb1845..95caa2731a 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -267,7 +267,6 @@ LLNavigationBar::LLNavigationBar() mBtnForward(NULL), mBtnHome(NULL), mCmbLocation(NULL), - mPurgeTPHistoryItems(false), mSaveToLocationHistory(false) { buildFromFile( "panel_navigation_bar.xml"); @@ -338,12 +337,6 @@ void LLNavigationBar::setVisible(BOOL visible) void LLNavigationBar::draw() { - if(mPurgeTPHistoryItems) - { - LLTeleportHistory::getInstance()->purgeItems(); - mPurgeTPHistoryItems = false; - } - if (isBackgroundVisible()) { static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0); @@ -687,7 +680,7 @@ void LLNavigationBar::clearHistoryCache() LLLocationHistory* lh = LLLocationHistory::getInstance(); lh->removeItems(); lh->save(); - mPurgeTPHistoryItems= true; + LLTeleportHistory::getInstance()->purgeItems(); } int LLNavigationBar::getDefNavBarHeight() diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index e4ce9e3998..7878bab24e 100644 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -145,7 +145,6 @@ private: boost::signals2::connection mTeleportFailedConnection; boost::signals2::connection mTeleportFinishConnection; boost::signals2::connection mHistoryMenuConnection; - bool mPurgeTPHistoryItems; // if true, save location to location history when teleport finishes bool mSaveToLocationHistory; }; diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 4512c14b7a..00ff81724c 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -34,6 +34,7 @@ #include "llfirstuse.h" #include "llnearbychatbar.h" +#include "llnearbychatbarlistener.h" #include "llagent.h" #include "llgesturemgr.h" #include "llmultigesture.h" @@ -80,6 +81,7 @@ LLNearbyChatBar::LLNearbyChatBar(const LLSD& key) mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); + mListener.reset(new LLNearbyChatBarListener(*this)); } //virtual @@ -103,15 +105,17 @@ BOOL LLNearbyChatBar::postBuild() mNearbyChat = getChildView("nearby_chat"); - LLUICtrl* show_btn = getChild<LLUICtrl>("show_nearby_chat"); + gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE); + BOOL show_nearby_chat = gSavedSettings.getBOOL("nearbychat_history_visibility"); + + LLButton* show_btn = getChild<LLButton>("show_nearby_chat"); show_btn->setCommitCallback(boost::bind(&LLNearbyChatBar::onToggleNearbyChatPanel, this)); + show_btn->setToggleState(show_nearby_chat); mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); mOutputMonitor->setVisible(FALSE); - gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE); - - mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility")); + showNearbyChatPanel(show_nearby_chat); // Register for font change notifications LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); @@ -124,7 +128,7 @@ BOOL LLNearbyChatBar::postBuild() // virtual void LLNearbyChatBar::onOpen(const LLSD& key) { - enableTranslationCheckbox(LLTranslate::isTranslationConfigured()); + showTranslationCheckbox(LLTranslate::isTranslationConfigured()); } bool LLNearbyChatBar::applyRectControl() @@ -170,9 +174,9 @@ void LLNearbyChatBar::showHistory() } } -void LLNearbyChatBar::enableTranslationCheckbox(BOOL enable) +void LLNearbyChatBar::showTranslationCheckbox(BOOL show) { - getChild<LLUICtrl>("translate_chat_checkbox")->setEnabled(enable); + getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show); } void LLNearbyChatBar::draw() @@ -392,26 +396,23 @@ void LLNearbyChatBar::sendChat( EChatType type ) } } - -void LLNearbyChatBar::onToggleNearbyChatPanel() +void LLNearbyChatBar::showNearbyChatPanel(bool show) { - LLView* nearby_chat = getChildView("nearby_chat"); - - if (nearby_chat->getVisible()) + if (!show) { - if (!isMinimized()) + if (mNearbyChat->getVisible() && !isMinimized()) { mExpandedHeight = getRect().getHeight(); } setResizeLimits(getMinWidth(), COLLAPSED_HEIGHT); - nearby_chat->setVisible(FALSE); + mNearbyChat->setVisible(FALSE); reshape(getRect().getWidth(), COLLAPSED_HEIGHT); enableResizeCtrls(true, true, false); storeRectControl(); } else { - nearby_chat->setVisible(TRUE); + mNearbyChat->setVisible(TRUE); setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); reshape(getRect().getWidth(), mExpandedHeight); enableResizeCtrls(true); @@ -421,6 +422,11 @@ void LLNearbyChatBar::onToggleNearbyChatPanel() gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible()); } +void LLNearbyChatBar::onToggleNearbyChatPanel() +{ + showNearbyChatPanel(!mNearbyChat->getVisible()); +} + void LLNearbyChatBar::setMinimized(BOOL b) { LLNearbyChat* nearby_chat = getChild<LLNearbyChat>("nearby_chat"); diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index baf12a06ea..662496d338 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -35,8 +35,12 @@ #include "lloutputmonitorctrl.h" #include "llspeakers.h" +class LLNearbyChatBarListener; + class LLNearbyChatBar : public LLFloater { + LOG_CLASS(LLNearbyChatBar); + public: // constructor for inline chat-bars (e.g. hosted in chat history window) LLNearbyChatBar(const LLSD& key); @@ -61,7 +65,7 @@ public: static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); void showHistory(); - void enableTranslationCheckbox(BOOL enable); + void showTranslationCheckbox(BOOL show); /*virtual*/void setMinimized(BOOL b); protected: @@ -76,6 +80,7 @@ protected: /* virtual */ bool applyRectControl(); + void showNearbyChatPanel(bool show); void onToggleNearbyChatPanel(); static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); @@ -92,6 +97,8 @@ protected: LLLocalSpeakerMgr* mSpeakerMgr; S32 mExpandedHeight; + + boost::shared_ptr<LLNearbyChatBarListener> mListener; }; #endif diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 240a7c7a35..600fd395fb 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -458,7 +458,9 @@ LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& i channel->setCreatePanelCallback(callback); - mChannel = LLChannelManager::getInstance()->addChannel(channel); + LLChannelManager::getInstance()->addChannel(channel); + + mChannel = channel->getHandle(); } LLNearbyChatHandler::~LLNearbyChatHandler() @@ -558,11 +560,12 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, && nearby_chat->isInVisibleChain() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) - || !mChannel->getShowToasts() ) // to prevent toasts in Busy mode + || mChannel.isDead() + || !mChannel.get()->getShowToasts() ) // to prevent toasts in Busy mode return;//no need in toast if chat is visible or if bubble chat is enabled // arrange a channel on a screen - if(!mChannel->getVisible()) + if(!mChannel.get()->getVisible()) { initChannel(); } @@ -579,7 +582,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } */ - LLNearbyChatScreenChannel* channel = dynamic_cast<LLNearbyChatScreenChannel*>(mChannel); + LLNearbyChatScreenChannel* channel = dynamic_cast<LLNearbyChatScreenChannel*>(mChannel.get()); if(channel) { diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 15d5d7c162..1bda7640bd 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -74,6 +74,8 @@ const F32 DOT_SCALE = 0.75f; const F32 MIN_PICK_SCALE = 2.f; const S32 MOUSE_DRAG_SLOP = 2; // How far the mouse needs to move before we think it's a drag +const F64 COARSEUPDATE_MAX_Z = 1020.0f; + LLNetMap::LLNetMap (const Params & p) : LLUICtrl (p), mBackgroundColor (p.bg_color()), @@ -300,7 +302,8 @@ void LLNetMap::draw() } LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal); - map_center_agent -= gAgentCamera.getCameraPositionAgent(); + LLVector3 camera_position = gAgentCamera.getCameraPositionAgent(); + map_center_agent -= camera_position; map_center_agent.mV[VX] *= mScale/region_width; map_center_agent.mV[VY] *= mScale/region_width; @@ -321,9 +324,6 @@ void LLNetMap::draw() gGL.popMatrix(); - LLVector3d pos_global; - LLVector3 pos_map; - // Mouse pointer in local coordinates S32 local_mouse_x; S32 local_mouse_y; @@ -333,90 +333,67 @@ void LLNetMap::draw() F32 closest_dist_squared = F32_MAX; // value will be overridden in the loop F32 min_pick_dist_squared = (mDotRadius * MIN_PICK_SCALE) * (mDotRadius * MIN_PICK_SCALE); + LLVector3 pos_map; + uuid_vec_t avatar_ids; + std::vector<LLVector3d> positions; + bool unknown_relative_z; + + LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgentCamera.getCameraPositionGlobal()); + // Draw avatars - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + for (U32 i = 0; i < avatar_ids.size(); i++) { - LLViewerRegion* regionp = *iter; - const LLVector3d& origin_global = regionp->getOriginGlobal(); - - S32 count = regionp->mMapAvatars.count(); - S32 i; - LLVector3 pos_local; - U32 compact_local; - U8 bits; - // TODO: it'd be very cool to draw these in sorted order from lowest Z to highest. - // just be careful to sort the avatar IDs along with the positions. -MG - for (i = 0; i < count; i++) - { - compact_local = regionp->mMapAvatars.get(i); + pos_map = globalPosToView(positions[i]); + LLUUID uuid = avatar_ids[i]; - bits = compact_local & 0xFF; - pos_local.mV[VZ] = F32(bits) * 4.f; - compact_local >>= 8; + bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); - bits = compact_local & 0xFF; - pos_local.mV[VY] = (F32)bits; - compact_local >>= 8; + LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color; - bits = compact_local & 0xFF; - pos_local.mV[VX] = (F32)bits; + unknown_relative_z = positions[i].mdV[VZ] == COARSEUPDATE_MAX_Z && + camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z; - pos_global.setVec( pos_local ); - pos_global += origin_global; + LLWorldMapView::drawAvatar( + pos_map.mV[VX], pos_map.mV[VY], + color, + pos_map.mV[VZ], mDotRadius, + unknown_relative_z); - pos_map = globalPosToView(pos_global); - - LLUUID uuid(NULL); - BOOL show_as_friend = FALSE; - if( i < regionp->mMapAvatarIDs.count()) + if(uuid.notNull()) + { + bool selected = false; + uuid_vec_t::iterator sel_iter = gmSelected.begin(); + for (; sel_iter != gmSelected.end(); sel_iter++) { - uuid = regionp->mMapAvatarIDs.get(i); - show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); + if(*sel_iter == uuid) + { + selected = true; + break; + } } - - LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color; - LLWorldMapView::drawAvatar( - pos_map.mV[VX], pos_map.mV[VY], - color, - pos_map.mV[VZ], mDotRadius); - - if(uuid.notNull()) + if(selected) { - bool selected = false; - uuid_vec_t::iterator sel_iter = gmSelected.begin(); - for (; sel_iter != gmSelected.end(); sel_iter++) + if( (pos_map.mV[VX] < 0) || + (pos_map.mV[VY] < 0) || + (pos_map.mV[VX] >= getRect().getWidth()) || + (pos_map.mV[VY] >= getRect().getHeight()) ) { - if(*sel_iter == uuid) - { - selected = true; - break; - } - } - if(selected) + S32 x = llround( pos_map.mV[VX] ); + S32 y = llround( pos_map.mV[VY] ); + LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10); + } else { - if( (pos_map.mV[VX] < 0) || - (pos_map.mV[VY] < 0) || - (pos_map.mV[VX] >= getRect().getWidth()) || - (pos_map.mV[VY] >= getRect().getHeight()) ) - { - S32 x = llround( pos_map.mV[VX] ); - S32 y = llround( pos_map.mV[VY] ); - LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10); - } else - { - LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f); - } + LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f); } } + } - F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), - LLVector2(local_mouse_x,local_mouse_y)); - if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) - { - closest_dist_squared = dist_to_cursor_squared; - mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i); - } + F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), + LLVector2(local_mouse_x,local_mouse_y)); + if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) + { + closest_dist_squared = dist_to_cursor_squared; + mClosestAgentToCursor = uuid; } } @@ -440,7 +417,7 @@ void LLNetMap::draw() } // Draw dot for self avatar position - pos_global = gAgent.getPositionGlobal(); + LLVector3d pos_global = gAgent.getPositionGlobal(); pos_map = globalPosToView(pos_global); S32 dot_width = llround(mDotRadius * 2.f); LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage; @@ -514,9 +491,11 @@ void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent) createObjectImage(); } -LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos ) +LLVector3 LLNetMap::globalPosToView(const LLVector3d& global_pos) { - LLVector3d relative_pos_global = global_pos - gAgentCamera.getCameraPositionGlobal(); + LLVector3d camera_position = gAgentCamera.getCameraPositionGlobal(); + + LLVector3d relative_pos_global = global_pos - camera_position; LLVector3 pos_local; pos_local.setVec(relative_pos_global); // convert to floats from doubles @@ -541,7 +520,7 @@ LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos ) void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color, BOOL draw_arrow ) { - LLVector3 pos_local = globalPosToView( pos_global ); + LLVector3 pos_local = globalPosToView(pos_global); if( (pos_local.mV[VX] < 0) || (pos_local.mV[VY] < 0) || (pos_local.mV[VX] >= getRect().getWidth()) || diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index 20fcee0814..1f7e7d68c6 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -33,9 +33,9 @@ #include "v3dmath.h" #include "v4color.h" #include "llpointer.h" +#include "llcoord.h" class LLColor4U; -class LLCoordGL; class LLImageRaw; class LLViewerTexture; class LLFloaterMap; diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index cae7d02fed..89fe7bb3c2 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -51,8 +51,8 @@ LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsMo p.channel_align = CA_CENTRE; // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->getChannel(p); - mChannel->setCanStoreToasts(false); + mChannel = LLChannelManager::getInstance()->getChannel(p)->getHandle(); + mChannel.get()->setCanStoreToasts(false); } //-------------------------------------------------------------------------- @@ -64,13 +64,13 @@ LLAlertHandler::~LLAlertHandler() void LLAlertHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().getWidth() / 2; - mChannel->init(channel_right_bound, channel_right_bound); + mChannel.get()->init(channel_right_bound, channel_right_bound); } //-------------------------------------------------------------------------- bool LLAlertHandler::processNotification(const LLSD& notify) { - if(!mChannel) + if(mChannel.isDead()) { return false; } @@ -81,7 +81,7 @@ bool LLAlertHandler::processNotification(const LLSD& notify) return false; // arrange a channel on a screen - if(!mChannel->getVisible()) + if(!mChannel.get()->getVisible()) { initChannel(); } @@ -114,22 +114,22 @@ bool LLAlertHandler::processNotification(const LLSD& notify) // Show alert in middle of progress view (during teleport) (EXT-1093) LLProgressView* progress = gViewerWindow->getProgressView(); LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); - mChannel->updatePositionAndSize(rc); + mChannel.get()->updatePositionAndSize(rc); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); } else if (notify["sigtype"].asString() == "change") { LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); } else { - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->killToastByNotificationID(notification->getID()); } diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 9b7fdaef82..ad51389241 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -42,10 +42,12 @@ LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id) mType = type; // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createNotificationChannel(); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) + { channel->setOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1)); + mChannel = channel->getHandle(); + } } //-------------------------------------------------------------------------- @@ -58,13 +60,13 @@ void LLGroupHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); } //-------------------------------------------------------------------------- bool LLGroupHandler::processNotification(const LLSD& notify) { - if(!mChannel) + if(mChannel.isDead()) { return false; } @@ -75,7 +77,7 @@ bool LLGroupHandler::processNotification(const LLSD& notify) return false; // arrange a channel on a screen - if(!mChannel->getVisible()) + if(!mChannel.get()->getVisible()) { initChannel(); } @@ -91,7 +93,7 @@ bool LLGroupHandler::processNotification(const LLSD& notify) p.panel = notify_box; p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); @@ -102,7 +104,7 @@ bool LLGroupHandler::processNotification(const LLSD& notify) } else if (notify["sigtype"].asString() == "delete") { - mChannel->killToastByNotificationID(notification->getID()); + mChannel.get()->killToastByNotificationID(notification->getID()); } return false; } diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 23dbb6b047..3569ad6447 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -103,8 +103,8 @@ protected: // at the moment, when a handlers creates a channel. virtual void initChannel()=0; - LLScreenChannelBase* mChannel; - e_notification_type mType; + LLHandle<LLScreenChannelBase> mChannel; + e_notification_type mType; }; diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 1b767e80d4..7c6287967a 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -64,7 +64,7 @@ LLSysHandler::LLSysHandler() void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) { - LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel.get()); if (channel == NULL) { return; diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 6105eff8ea..f792f53ac5 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -35,6 +35,7 @@ #include "llnotifications.h" #include <boost/bind.hpp> +#include <boost/foreach.hpp> using namespace LLNotificationsUI; @@ -48,6 +49,10 @@ LLNotificationManager::LLNotificationManager() //-------------------------------------------------------------------------- LLNotificationManager::~LLNotificationManager() { + BOOST_FOREACH(listener_pair_t& pair, mChannelListeners) + { + pair.second.disconnect(); + } } //-------------------------------------------------------------------------- @@ -64,16 +69,16 @@ void LLNotificationManager::init() LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")); LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")); - LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); - LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); - LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); + mChannelListeners["Notifications"] = LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); + mChannelListeners["NotificationTips"] = LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); + mChannelListeners["Group Notifications"] = LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); + mChannelListeners["Alerts"] = LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); + mChannelListeners["AlertModal"] = LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); + mChannelListeners["IM Notifications"] = LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); + mChannelListeners["Offer"] = LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); + mChannelListeners["Hints"] = LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); + mChannelListeners["Browser"] = LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); + mChannelListeners["Outbox"] = LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD())); mNotifyHandlers["notifytip"] = boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); @@ -92,6 +97,9 @@ bool LLNotificationManager::onNotification(const LLSD& notify) { LLSysHandler* handle = NULL; + if (LLNotifications::destroyed()) + return false; + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if (!notification) diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 16e82e4cce..27b6ba1c71 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -28,6 +28,8 @@ #ifndef LL_LLNOTIFICATIONMANAGER_H #define LL_LLNOTIFICATIONMANAGER_H +#include "llevents.h" + #include "lluictrl.h" #include "llnotificationhandler.h" @@ -47,6 +49,7 @@ class LLToast; class LLNotificationManager : public LLSingleton<LLNotificationManager> { typedef std::pair<std::string, LLEventHandler*> eventhandlers; + typedef std::pair<const std::string, LLBoundListener> listener_pair_t; public: LLNotificationManager(); virtual ~LLNotificationManager(); @@ -70,6 +73,8 @@ private: //TODO (*) std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers; // cruft std::map<std::string, LLChatHandler*> mChatHandlers; + + std::map<std::string, LLBoundListener> mChannelListeners; }; } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 68fd65be0f..1552ed3346 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -45,12 +45,13 @@ LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id) mType = type; // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createNotificationChannel(); - mChannel->setControlHovering(true); - - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) + { + channel->setControlHovering(true); channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); + mChannel = channel->getHandle(); + } } //-------------------------------------------------------------------------- @@ -63,13 +64,13 @@ void LLOfferHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); } //-------------------------------------------------------------------------- bool LLOfferHandler::processNotification(const LLSD& notify) { - if(!mChannel) + if(mChannel.isDead()) { return false; } @@ -80,7 +81,7 @@ bool LLOfferHandler::processNotification(const LLSD& notify) return false; // arrange a channel on a screen - if(!mChannel->getVisible()) + if(!mChannel.get()->getVisible()) { initChannel(); } @@ -134,7 +135,7 @@ bool LLOfferHandler::processNotification(const LLSD& notify) // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notid_to_im; - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); @@ -175,7 +176,7 @@ bool LLOfferHandler::processNotification(const LLSD& notify) { LLHandlerUtil::decIMMesageCounter(notification); } - mChannel->killToastByNotificationID(notification->getID()); + mChannel.get()->killToastByNotificationID(notification->getID()); } } diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index bbb4d03768..398f54c6f7 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -47,13 +47,13 @@ LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) mType = type; // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createNotificationChannel(); - mChannel->setControlHovering(true); - - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) + { + channel->setControlHovering(true); channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); - + mChannel = channel->getHandle(); + } } //-------------------------------------------------------------------------- @@ -66,13 +66,13 @@ void LLScriptHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); } //-------------------------------------------------------------------------- bool LLScriptHandler::processNotification(const LLSD& notify) { - if(!mChannel) + if(mChannel.isDead()) { return false; } @@ -83,7 +83,7 @@ bool LLScriptHandler::processNotification(const LLSD& notify) return false; // arrange a channel on a screen - if(!mChannel->getVisible()) + if(!mChannel.get()->getVisible()) { initChannel(); } @@ -101,7 +101,7 @@ bool LLScriptHandler::processNotification(const LLSD& notify) } else { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); LLToast::Params p; p.notif_id = notification->getID(); @@ -109,7 +109,7 @@ bool LLScriptHandler::processNotification(const LLSD& notify) p.panel = notify_box; p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) { channel->addToast(p); @@ -127,7 +127,7 @@ bool LLScriptHandler::processNotification(const LLSD& notify) } else { - mChannel->killToastByNotificationID(notification->getID()); + mChannel.get()->killToastByNotificationID(notification->getID()); } } return false; diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index fb0891c4c5..e397cfa046 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -46,11 +46,12 @@ LLTipHandler::LLTipHandler(e_notification_type type, const LLSD& id) mType = type; // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createNotificationChannel(); - - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) + { channel->setOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1)); + mChannel = channel->getHandle(); + } } //-------------------------------------------------------------------------- @@ -63,13 +64,13 @@ void LLTipHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); } //-------------------------------------------------------------------------- bool LLTipHandler::processNotification(const LLSD& notify) { - if(!mChannel) + if(mChannel.isDead()) { return false; } @@ -80,7 +81,7 @@ bool LLTipHandler::processNotification(const LLSD& notify) return false; // arrange a channel on a screen - if(!mChannel->getVisible()) + if(!mChannel.get()->getVisible()) { initChannel(); } @@ -137,13 +138,13 @@ bool LLTipHandler::processNotification(const LLSD& notify) removeExclusiveNotifications(notification); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); } else if (notify["sigtype"].asString() == "delete") { - mChannel->killToastByNotificationID(notification->getID()); + mChannel.get()->killToastByNotificationID(notification->getID()); } return false; } diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 1dc4d796ab..ef5ef2ddc8 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -640,7 +640,7 @@ void LLOutfitsList::onOutfitsRemovalConfirmation(const LLSD& notification, const if (mSelectedOutfitUUID.notNull()) { - remove_category(&gInventory, mSelectedOutfitUUID); + gInventory.removeCategory(mSelectedOutfitUUID); } } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index a4f6921f98..7301b305b2 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -875,8 +875,15 @@ void LLPanelFace::getState() { getChild<LLUICtrl>("TexScaleU")->setValue(2.0f * getChild<LLUICtrl>("TexScaleU")->getValue().asReal() ); getChild<LLUICtrl>("TexScaleV")->setValue(2.0f * getChild<LLUICtrl>("TexScaleV")->getValue().asReal() ); - } + // EXP-1507 (change label based on the mapping mode) + getChild<LLUICtrl>("rpt")->setValue(getString("string repeats per meter")); + } + else + if (selected_texgen == 0) // FIXME: should not be magic numbers + { + getChild<LLUICtrl>("rpt")->setValue(getString("string repeats per face")); + } } { diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index ca48e8561b..7a15d93181 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -289,12 +289,12 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata) //Soon the avatar picker will be embedded into this panel //instead of being it's own separate floater. But that is next week. //This will do for now. -jwolk May 10, 2006 - LLFloater* parentp; - - parentp = gFloaterView->getParentFloater(panelp); - parentp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(impl::callbackAddUsers, _1, - panelp->mImplementation), - TRUE)); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( + boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE); + if (picker) + { + gFloaterView->getParentFloater(panelp)->addDependentFloater(picker); + } } } diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index fbe331c7ab..f825ee3215 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -749,7 +749,10 @@ LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab() LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab() { - gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName()); + if (mMembersList) + { + gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName()); + } } BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root) diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 0295ad151f..eda0749cdb 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -374,7 +374,7 @@ void LLPanelGroupControlPanel::draw() { // Need to resort the participant list if it's in sort by recent speaker order. if (mParticipantList) - mParticipantList->updateRecentSpeakersOrder(); + mParticipantList->update(); LLPanelChatControlPanel::draw(); } diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index c7454e85a9..68a3b6d1cd 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -1149,7 +1149,7 @@ Rules: - cut/rename/delete in any other accordions - paste - only in Favorites, Landmarks accordions 3. For Folders we can: perform any action in Landmarks accordion, except Received folder - 4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste()) + 4. We can paste folders from Clipboard (processed by LLFolderView::canPaste()) 5. Check LLFolderView/Inventory Bridges rules */ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFolderViewItem* item) const @@ -1206,8 +1206,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold if ("cut" == command_name) { - // "Cut" disabled for folders. See EXT-8697. - can_be_modified = root_folder->canCut() && listenerp->getInventoryType() != LLInventoryType::IT_CATEGORY; + can_be_modified = root_folder->canCut(); } else if ("rename" == command_name) { diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 058d1ad6bc..76aadcd913 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -216,6 +216,7 @@ void LLPanelLogin::addUsersWithFavoritesToUsername() void LLPanelLogin::addFavoritesToStartLocation() { + // Clear the combo. LLComboBox* combo = getChild<LLComboBox>("start_location_combo"); if (!combo) return; int num_items = combo->getItemCount(); @@ -223,6 +224,10 @@ void LLPanelLogin::addFavoritesToStartLocation() { combo->remove(i); } + + // Load favorites into the combo. + std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple(); + std::string canonical_user_name = canonicalize_username(user_defined_name); std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); LLSD fav_llsd; llifstream file; @@ -232,15 +237,18 @@ void LLPanelLogin::addFavoritesToStartLocation() for (LLSD::map_const_iterator iter = fav_llsd.beginMap(); iter != fav_llsd.endMap(); ++iter) { - std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple(); - // The account name in stored_favorites.xml has Resident last name even if user has // a single word account name, so it can be compared case-insensitive with the // user defined "firstname lastname". - S32 res = LLStringUtil::compareInsensitive(canonicalize_username(user_defined_name), iter->first); - if (res != 0) continue; + S32 res = LLStringUtil::compareInsensitive(canonical_user_name, iter->first); + if (res != 0) + { + lldebugs << "Skipping favorites for " << iter->first << llendl; + continue; + } combo->addSeparator(); + lldebugs << "Loading favorites for " << iter->first << llendl; LLSD user_llsd = iter->second; for (LLSD::array_const_iterator iter1 = user_llsd.beginArray(); iter1 != user_llsd.endArray(); ++iter1) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 374afb90be..c11597f532 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -375,7 +375,7 @@ void LLPanelMainInventory::onClearSearch() if (mActivePanel) { mActivePanel->setFilterSubString(LLStringUtil::null); - mActivePanel->setFilterTypes(0xffffffff); + mActivePanel->setFilterTypes(0xffffffffffffffffULL); mActivePanel->setFilterLinks(LLInventoryFilter::FILTERLINK_INCLUDE_LINKS); } @@ -567,7 +567,7 @@ void LLPanelMainInventory::updateItemcountText() std::string text = ""; - if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()) + if (LLInventoryModelBackgroundFetch::instance().folderFetchActive()) { text = getString("ItemcountFetching", string_args); } @@ -726,7 +726,7 @@ void LLFloaterInventoryFinder::updateElementsFromFilter() void LLFloaterInventoryFinder::draw() { LLMemType mt(LLMemType::MTYPE_INVENTORY_DRAW); - U32 filter = 0xffffffff; + U64 filter = 0xffffffffffffffffULL; BOOL filtered_by_all_types = TRUE; if (!getChild<LLUICtrl>("check_animation")->getValue()) diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 98ea680504..1ca24f3031 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -124,7 +124,7 @@ public: virtual void move(LLFolderViewEventListener* parent_listener); virtual BOOL isItemCopyable() const; virtual BOOL copyToClipboard() const; - virtual void cutToClipboard(); + virtual BOOL cutToClipboard() const; virtual BOOL isClipboardPasteable() const; virtual void pasteFromClipboard(); virtual void pasteLinkFromClipboard(); @@ -524,8 +524,9 @@ BOOL LLTaskInvFVBridge::copyToClipboard() const return FALSE; } -void LLTaskInvFVBridge::cutToClipboard() +BOOL LLTaskInvFVBridge::cutToClipboard() const { + return FALSE; } BOOL LLTaskInvFVBridge::isClipboardPasteable() const @@ -1568,7 +1569,7 @@ void LLPanelObjectInventory::reset() scroll_p.rect(scroller_rect); scroll_p.tab_stop(true); scroll_p.follows.flags(FOLLOWS_ALL); - mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_p); + mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroll_p); addChild(mScroller); mScroller->addChild(mFolders); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 9c46f04abf..f1380e7a36 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1162,8 +1162,13 @@ void LLPanelPeople::onAddFriendWizButtonClicked() { // Show add friend wizard. LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE); + if (!picker) + { + return; + } + // Need to disable 'ok' button when friend occurs in selection - if (picker) picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1)); + picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1)); LLFloater* root_floater = gFloaterView->getParentFloater(this); if (root_floater) { diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 39c0628cbe..76d38f067d 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -818,7 +818,7 @@ bool LLPanelPrimMediaControls::isMouseOver() LLCoordGL cursor_pos_gl; S32 x, y; getWindow()->getCursorPosition(&cursor_pos_window); - getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); + cursor_pos_gl = cursor_pos_window.convert(); if(mMediaControlsStack->getVisible()) { diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 66956181f2..eeb433e306 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -30,9 +30,9 @@ #include "llpanel.h" #include "llviewermedia.h" #include "llnotificationptr.h" +#include "llcoord.h" class LLButton; -class LLCoordWindow; class LLIconCtrl; class LLLayoutStack; class LLProgressBar; diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 1f1cccad85..c63d89fc98 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -358,7 +358,7 @@ void LLTeleportHistoryPanel::ContextMenu::onInfo() //static void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& slurl) { - gClipboard.copyFromString(utf8str_to_wstring(slurl)); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl),0,slurl.size()); } void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard() diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index eb4c7572d4..280cc11179 100644 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -467,7 +467,7 @@ void LLPanelTopInfoBar::onContextMenuItemClicked(const LLSD::String& item) LLAgentUI::buildSLURL(slurl, false); LLUIString location_str(slurl.getSLURLString()); - gClipboard.copyFromString(location_str); + LLClipboard::instance().copyToClipboard(location_str,0,location_str.length()); } } diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp index 4bbfec8ab7..5fec6d967d 100644 --- a/indra/newview/llpanelvoiceeffect.cpp +++ b/indra/newview/llpanelvoiceeffect.cpp @@ -123,7 +123,6 @@ void LLPanelVoiceEffect::update(bool list_updated) if (mVoiceEffectCombo) { LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - llassert(effect_interface); if (!effect_interface) return; if (list_updated) { diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index e2801c09bd..3b9934d4be 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -302,6 +302,6 @@ void LLPanelWearing::copyToClipboard() } } - gClipboard.copyFromString(utf8str_to_wstring(text)); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(text),0,text.size()); } // EOF diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 5c95e805ce..975a6c67d8 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -390,7 +390,10 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) { const LLPointer<LLSpeaker>& speakerp = *it; - update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); + if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) + { + update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); + } } } } @@ -466,12 +469,12 @@ void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t c mValidateSpeakerCallback = cb; } -void LLParticipantList::updateRecentSpeakersOrder() +void LLParticipantList::update() { + mSpeakerMgr->update(true); + if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered()) { - // Need to update speakers to sort list correctly - mSpeakerMgr->update(true); // Resort avatar list sort(); } @@ -760,6 +763,7 @@ void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(speaker_id); if (speakerp.isNull()) { + LL_WARNS("Speakers") << "Speaker " << speaker_id << " not found" << llendl; return; } LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mParent.mAvatarList->getItemByValue(speaker_id)); diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index a001d29b67..53966c15fe 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -72,9 +72,9 @@ public: const EParticipantSortOrder getSortOrder() const; /** - * Refreshes the participant list if it's in sort by recent speaker order. + * Refreshes the participant list. */ - void updateRecentSpeakersOrder(); + void update(); /** * Set a callback to be called before adding a speaker. Invalid speakers will not be added. diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index 225ac6e224..fe4cc0f55f 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -89,7 +89,7 @@ void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) std::vector<std::string> items; std::vector<std::string> disabled_items; - LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLInventoryPanel* inv_panel = mInventoryPanel.get(); bool is_open = false; if (inv_panel) { @@ -137,7 +137,7 @@ void LLPlacesFolderBridge::performAction(LLInventoryModel* model, std::string ac LLFolderViewFolder* LLPlacesFolderBridge::getFolder() { LLFolderViewFolder* folder = NULL; - LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLInventoryPanel* inv_panel = mInventoryPanel.get(); if (inv_panel) { folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); diff --git a/indra/newview/llpopupview.cpp b/indra/newview/llpopupview.cpp index 9fbb67a63a..08829c1184 100644 --- a/indra/newview/llpopupview.cpp +++ b/indra/newview/llpopupview.cpp @@ -83,7 +83,7 @@ void LLPopupView::draw() LLUI::pushMatrix(); { - LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f); + LLUI::translate( (F32) screen_x, (F32) screen_y); popup->draw(); } LLUI::popMatrix(); diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index 896e17c3c3..759430c3a5 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -32,6 +32,7 @@ #include "llpointer.h" #include "lluuid.h" #include "llinventoryobserver.h" +#include "llextendedstatus.h" #include <map> class LLInventoryItem; diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index 8e8b530e13..35ac0537a3 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -43,19 +43,7 @@ extern LLAgent gAgent; LLPreviewAnim::LLPreviewAnim(const LLSD& key) : LLPreview( key ) { -} - -// static -void LLPreviewAnim::endAnimCallback( void *userdata ) -{ - LLHandle<LLFloater>* handlep = ((LLHandle<LLFloater>*)userdata); - LLFloater* self = handlep->get(); - delete handlep; // done with the handle - if (self) - { - self->getChild<LLUICtrl>("Anim play btn")->setValue(FALSE); - self->getChild<LLUICtrl>("Anim audition btn")->setValue(FALSE); - } + mCommitCallbackRegistrar.add("PreviewAnim.Play", boost::bind(&LLPreviewAnim::play, this, _2)); } // virtual @@ -68,106 +56,115 @@ BOOL LLPreviewAnim::postBuild() getChild<LLUICtrl>("desc")->setValue(item->getDescription()); } - childSetAction("Anim play btn",playAnim, this); - childSetAction("Anim audition btn",auditionAnim, this); - childSetCommitCallback("desc", LLPreview::onText, this); getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); - + return LLPreview::postBuild(); } -void LLPreviewAnim::activate(e_activation_type type) +// static +// llinventorybridge also calls into here +void LLPreviewAnim::play(const LLSD& param) { - switch ( type ) + const LLInventoryItem *item = getItem(); + + if(item) { - case PLAY: + LLUUID itemID=item->getAssetUUID(); + + std::string btn_name = param.asString(); + LLButton* btn_inuse; + LLButton* btn_other; + + if ("Inworld" == btn_name) { - playAnim( (void *) this ); - break; + btn_inuse = getChild<LLButton>("Inworld"); + btn_other = getChild<LLButton>("Locally"); } - case AUDITION: + else if ("Locally" == btn_name) { - auditionAnim( (void *) this ); - break; + btn_inuse = getChild<LLButton>("Locally"); + btn_other = getChild<LLButton>("Inworld"); } - default: + else { - //do nothing + return; } - } -} - -// static -void LLPreviewAnim::playAnim( void *userdata ) -{ - LLPreviewAnim* self = (LLPreviewAnim*) userdata; - const LLInventoryItem *item = self->getItem(); - if(item) - { - LLUUID itemID=item->getAssetUUID(); + if (btn_inuse) + { + btn_inuse->toggleState(); + } - LLButton* btn = self->getChild<LLButton>("Anim play btn"); - if (btn) + if (btn_other) { - btn->toggleState(); + btn_other->setEnabled(false); } - if (self->getChild<LLUICtrl>("Anim play btn")->getValue().asBoolean() ) + if (getChild<LLUICtrl>(btn_name)->getValue().asBoolean() ) { - self->mPauseRequest = NULL; - gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_START); + if("Inworld" == btn_name) + { + gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_START); + } + else + { + gAgentAvatarp->startMotion(item->getAssetUUID()); + } + LLMotion* motion = gAgentAvatarp->findMotion(itemID); if (motion) { - motion->setDeactivateCallback(&endAnimCallback, (void *)(new LLHandle<LLFloater>(self->getHandle()))); + mItemID = itemID; + mDidStart = false; } } else { gAgentAvatarp->stopMotion(itemID); gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_STOP); + + if (btn_other) + { + btn_other->setEnabled(true); + } } } } -// static -void LLPreviewAnim::auditionAnim( void *userdata ) +// virtual +void LLPreviewAnim::draw() { - LLPreviewAnim* self = (LLPreviewAnim*) userdata; - const LLInventoryItem *item = self->getItem(); - - if(item) + LLPreview::draw(); + if (!this->mItemID.isNull()) { - LLUUID itemID=item->getAssetUUID(); - - LLButton* btn = self->getChild<LLButton>("Anim audition btn"); - if (btn) - { - btn->toggleState(); - } - - if (self->getChild<LLUICtrl>("Anim audition btn")->getValue().asBoolean() ) + LLMotion* motion = gAgentAvatarp->findMotion(this->mItemID); + if (motion) { - self->mPauseRequest = NULL; - gAgentAvatarp->startMotion(item->getAssetUUID()); - LLMotion* motion = gAgentAvatarp->findMotion(itemID); - - if (motion) + if (motion->isStopped() && this->mDidStart) { - motion->setDeactivateCallback(&endAnimCallback, (void *)(new LLHandle<LLFloater>(self->getHandle()))); + cleanup(); + } + if(gAgentAvatarp->isMotionActive(this->mItemID) && !this->mDidStart) + { + this->mDidStart = true; } - } - else - { - gAgentAvatarp->stopMotion(itemID); - gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_STOP); } } } // virtual +void LLPreviewAnim::cleanup() +{ + this->mItemID = LLUUID::null; + this->mDidStart = false; + getChild<LLUICtrl>("Inworld")->setValue(FALSE); + getChild<LLUICtrl>("Locally")->setValue(FALSE); + getChild<LLUICtrl>("Inworld")->setEnabled(true); + getChild<LLUICtrl>("Locally")->setEnabled(true); +} + +// virtual void LLPreviewAnim::onClose(bool app_quitting) { const LLInventoryItem *item = getItem(); @@ -176,12 +173,5 @@ void LLPreviewAnim::onClose(bool app_quitting) { gAgentAvatarp->stopMotion(item->getAssetUUID()); gAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP); - LLMotion* motion = gAgentAvatarp->findMotion(item->getAssetUUID()); - - if (motion) - { - // *TODO: minor memory leak here, user data is never deleted (Use real callbacks) - motion->setDeactivateCallback(NULL, (void *)NULL); - } } } diff --git a/indra/newview/llpreviewanim.h b/indra/newview/llpreviewanim.h index 32e07ee33a..8eaed6ca1f 100644 --- a/indra/newview/llpreviewanim.h +++ b/indra/newview/llpreviewanim.h @@ -33,24 +33,18 @@ class LLPreviewAnim : public LLPreview { public: - enum e_activation_type { NONE = 0, PLAY = 1, AUDITION = 2 }; - LLPreviewAnim(const LLSD& key); - static void playAnim( void* userdata ); - static void auditionAnim( void* userdata ); - static void endAnimCallback( void *userdata ); + LLPreviewAnim(const LLSD& key); /*virtual*/ BOOL postBuild(); /*virtual*/ void onClose(bool app_quitting); - void activate(e_activation_type type); + void draw(); + void cleanup(); + void play(const LLSD& param); protected: - LLAnimPauseRequest mPauseRequest; - LLUUID mItemID; - std::string mTitle; - LLUUID mObjectID; - LLButton* mPlayBtn; - LLButton* mAuditionBtn; + LLUUID mItemID; + bool mDidStart; }; -#endif // LL_LLPREVIEWSOUND_H +#endif // LL_LLPREVIEWANIM_H diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 4974dde282..3a9360fd23 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -29,7 +29,6 @@ #include "llpreviewnotecard.h" #include "llinventory.h" -#include "llinventoryfunctions.h" // for change_item_parent() #include "llagent.h" #include "llassetuploadresponders.h" @@ -494,7 +493,7 @@ void LLPreviewNotecard::deleteNotecard() if (item != NULL) { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - change_item_parent(&gInventory, item, trash_id, FALSE); + gInventory.changeItemParent(item, trash_id, FALSE); } closeFloater(); diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 5d7a5b1c59..f86e583b9e 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -40,6 +40,7 @@ #include "llagent.h" #include "llbutton.h" +#include "llcallbacklist.h" #include "llfocusmgr.h" #include "llnotifications.h" #include "llprogressbar.h" @@ -72,6 +73,8 @@ LLProgressView::LLProgressView() mStartupComplete(false) { mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1)); + mFadeToWorldTimer.stop(); + mFadeFromLoginTimer.stop(); } BOOL LLProgressView::postBuild() @@ -87,8 +90,6 @@ BOOL LLProgressView::postBuild() mCancelBtn = getChild<LLButton>("cancel_btn"); mCancelBtn->setClickedCallback( LLProgressView::onCancelButtonClicked, NULL ); - mFadeToWorldTimer.stop(); - mFadeFromLoginTimer.stop(); getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle())); @@ -106,6 +107,9 @@ BOOL LLProgressView::postBuild() LLProgressView::~LLProgressView() { + // Just in case something went wrong, make sure we deregister our idle callback. + gIdleCallbacks.deleteFunction(onIdle, this); + gFocusMgr.releaseFocusIfNeeded( this ); sInstance = NULL; @@ -154,6 +158,7 @@ void LLProgressView::revealIntroPanel() } mFadeFromLoginTimer.start(); + gIdleCallbacks.addFunction(onIdle, this); } void LLProgressView::setStartupComplete() @@ -236,13 +241,6 @@ void LLProgressView::draw() } LLPanel::draw(); - - if (mFadeFromLoginTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME ) - { - mFadeFromLoginTimer.stop(); - LLPanelLogin::closePanel(); - } - return; } @@ -424,3 +422,21 @@ void LLProgressView::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent even } } } + + +// static +void LLProgressView::onIdle(void* user_data) +{ + LLProgressView* self = (LLProgressView*) user_data; + + // Close login panel on mFadeToWorldTimer expiration. + if (self->mFadeFromLoginTimer.getStarted() && + self->mFadeFromLoginTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME) + { + self->mFadeFromLoginTimer.stop(); + LLPanelLogin::closePanel(); + + // Nothing to do anymore. + gIdleCallbacks.deleteFunction(onIdle, user_data); + } +} diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index fac00ad04d..813576b21d 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -41,6 +41,8 @@ class LLProgressView : public LLViewerMediaObserver { + LOG_CLASS(LLProgressView); + public: LLProgressView(); virtual ~LLProgressView(); @@ -74,10 +76,6 @@ public: static void onClickMessage(void*); bool onAlertModal(const LLSD& sd); - // note - this is not just hiding the intro panel - it also hides the parent panel - // and is used when the intro is finished and we want to show the world - void removeIntroPanel(); - protected: LLProgressBar* mProgressBar; LLMediaCtrl* mMediaCtrl; @@ -96,6 +94,7 @@ protected: LLEventStream mUpdateEvents; bool handleUpdate(const LLSD& event_data); + static void onIdle(void* user_data); }; #endif // LL_LLPROGRESSVIEW_H diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 5301955964..d340b304ca 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -195,17 +195,18 @@ LLScreenChannel::~LLScreenChannel() } -std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) +std::list<const LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) { - std::list<LLToast*> res; + std::list<const LLToast*> res; // collect stored toasts for (std::vector<ToastElem>::iterator it = mStoredToastList.begin(); it != mStoredToastList.end(); it++) { - if (matcher.matches(it->toast->getNotification())) + const LLToast* toast = it->getToast(); + if (toast && matcher.matches(toast->getNotification())) { - res.push_back(it->toast); + res.push_back(toast); } } @@ -213,9 +214,10 @@ std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) for (std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) { - if (matcher.matches(it->toast->getNotification())) + const LLToast* toast = it->getToast(); + if (toast && matcher.matches(toast->getNotification())) { - res.push_back(it->toast); + res.push_back(toast); } } @@ -260,15 +262,16 @@ void LLScreenChannel::addToast(const LLToast::Params& p) return; } - ToastElem new_toast_elem(p); + LLToast* toast = new LLToast(p); + ToastElem new_toast_elem(toast->getHandle()); - new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); - new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); + toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); + toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); if(mControlHovering) { - new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); - new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, new_toast_elem.toast)); - new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, new_toast_elem.toast)); + toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); + toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, toast)); + toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, toast)); } if(show_toast) @@ -340,13 +343,13 @@ void LLScreenChannel::onToastFade(LLToast* toast) //-------------------------------------------------------------------------- void LLScreenChannel::deleteToast(LLToast* toast) { - if (toast->isDead()) + if (!toast || toast->isDead()) { return; } // send signal to observers about destroying of a toast - toast->mOnDeleteToastSignal(toast); + toast->closeToast(); // update channel's Hovering state // turning hovering off manually because onMouseLeave won't happen if a toast was closed using a keyboard @@ -354,9 +357,6 @@ void LLScreenChannel::deleteToast(LLToast* toast) { mHoveredToast = NULL; } - - // close the toast - toast->closeFloater(); } //-------------------------------------------------------------------------- @@ -364,12 +364,16 @@ void LLScreenChannel::deleteToast(LLToast* toast) void LLScreenChannel::storeToast(ToastElem& toast_elem) { // do not store clones - std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.id); + std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.getID()); if( it != mStoredToastList.end() ) return; - mStoredToastList.push_back(toast_elem); - mOnStoreToast(toast_elem.toast->getPanel(), toast_elem.id); + const LLToast* toast = toast_elem.getToast(); + if (toast) + { + mStoredToastList.push_back(toast_elem); + mOnStoreToast(toast->getPanel(), toast->getNotificationID()); + } } //-------------------------------------------------------------------------- @@ -382,9 +386,13 @@ void LLScreenChannel::loadStoredToastsToChannel() for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it) { - (*it).toast->setIsHidden(false); - (*it).toast->startTimer(); - mToastList.push_back((*it)); + LLToast* toast = it->getToast(); + if (toast) + { + toast->setIsHidden(false); + toast->startTimer(); + mToastList.push_back(*it); + } } mStoredToastList.clear(); @@ -399,17 +407,19 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) if( it == mStoredToastList.end() ) return; - LLToast* toast = (*it).toast; - - if(toast->getVisible()) + LLToast* toast = it->getToast(); + if (toast) { - // toast is already in channel - return; - } + if(toast->getVisible()) + { + // toast is already in channel + return; + } - toast->setIsHidden(false); - toast->startTimer(); - mToastList.push_back((*it)); + toast->setIsHidden(false); + toast->startTimer(); + mToastList.push_back(*it); + } redrawToasts(); } @@ -423,9 +433,19 @@ void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) if( it == mStoredToastList.end() ) return; - LLToast* toast = (*it).toast; - mStoredToastList.erase(it); - mRejectToastSignal(toast->getNotificationID()); + const LLToast* toast = it->getToast(); + if (toast) + { + mRejectToastSignal(toast->getNotificationID()); + } + + // Call find() once more, because the mStoredToastList could have been changed + // in mRejectToastSignal callback and the iterator could have become invalid. + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) + { + mStoredToastList.erase(it); + } } //-------------------------------------------------------------------------- @@ -436,21 +456,22 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) if( it != mToastList.end()) { - LLToast* toast = (*it).toast; + LLToast* toast = it->getToast(); // if it is a notification toast and notification is UnResponded - then respond on it // else - simply destroy a toast // // NOTE: if a notification is unresponded this function will be called twice for the same toast. // At first, the notification will be discarded, at second (it will be caused by discarding), // the toast will be destroyed. - if(toast->isNotificationValid()) + if(toast && toast->isNotificationValid()) { mRejectToastSignal(toast->getNotificationID()); } else { - mToastList.erase(it); + deleteToast(toast); + mToastList.erase(it); redrawToasts(); } return; @@ -459,20 +480,31 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) // searching among stored toasts it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - if( it != mStoredToastList.end() ) + if (it != mStoredToastList.end()) + { + LLToast* toast = it->getToast(); + if (toast) + { + // send signal to a listener to let him perform some action on toast rejecting + mRejectToastSignal(toast->getNotificationID()); + deleteToast(toast); + } + } + + // Call find() once more, because the mStoredToastList could have been changed + // in mRejectToastSignal callback and the iterator could have become invalid. + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) { - LLToast* toast = (*it).toast; mStoredToastList.erase(it); - // send signal to a listener to let him perform some action on toast rejecting - mRejectToastSignal(toast->getNotificationID()); - deleteToast(toast); } + } void LLScreenChannel::killMatchedToasts(const Matcher& matcher) { - std::list<LLToast*> to_delete = findToasts(matcher); - for (std::list<LLToast*>::iterator it = to_delete.begin(); it + std::list<const LLToast*> to_delete = findToasts(matcher); + for (std::list<const LLToast*>::iterator it = to_delete.begin(); it != to_delete.end(); it++) { killToastByNotificationID((*it)-> getNotificationID()); @@ -486,12 +518,15 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel) if( it != mToastList.end() && panel) { - LLToast* toast = (*it).toast; - LLPanel* old_panel = toast->getPanel(); - toast->removeChild(old_panel); - delete old_panel; - toast->insertPanel(panel); - toast->startTimer(); + LLToast* toast = it->getToast(); + if (toast) + { + LLPanel* old_panel = toast->getPanel(); + toast->removeChild(old_panel); + delete old_panel; + toast->insertPanel(panel); + toast->startTimer(); + } redrawToasts(); } } @@ -540,16 +575,29 @@ void LLScreenChannel::showToastsBottom() { if(it != mToastList.rbegin()) { - LLToast* toast = (*(it-1)).toast; + LLToast* toast = (it-1)->getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + bottom = toast->getRect().mTop - toast->getTopPad(); toast_margin = gSavedSettings.getS32("ToastGap"); } - toast_rect = (*it).toast->getRect(); + LLToast* toast = it->getToast(); + if(!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + toast_rect = toast->getRect(); toast_rect.setOriginAndSize(getRect().mRight - toast_rect.getWidth(), bottom + toast_margin, toast_rect.getWidth(), toast_rect.getHeight()); - (*it).toast->setRect(toast_rect); + toast->setRect(toast_rect); if(floater && floater->overlapsScreenChannel()) { @@ -561,7 +609,7 @@ void LLScreenChannel::showToastsBottom() { shift += floater->getDockControl()->getTongueHeight(); } - (*it).toast->translate(0, shift); + toast->translate(0, shift); } LLRect channel_rect = getChannelRect(); @@ -572,13 +620,13 @@ void LLScreenChannel::showToastsBottom() } } - bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop; + bool stop_showing_toasts = toast->getRect().mTop > getRect().mTop; if(!stop_showing_toasts) { if( it != mToastList.rend()-1) { - S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap"); + S32 toast_top = toast->getRect().mTop + gSavedSettings.getS32("ToastGap"); stop_showing_toasts = toast_top > getRect().mTop; } } @@ -592,17 +640,17 @@ void LLScreenChannel::showToastsBottom() if(stop_showing_toasts) break; - if( !(*it).toast->getVisible() ) + if( !toast->getVisible() ) { // HACK // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts - (*it).toast->setVisible(TRUE); + toast->setVisible(TRUE); } - if(!(*it).toast->hasFocus()) + if(!toast->hasFocus()) { // Fixing Z-order of toasts (EXT-4862) // Next toast will be positioned under this one. - gFloaterView->sendChildToBack((*it).toast); + gFloaterView->sendChildToBack(toast); } } @@ -612,7 +660,11 @@ void LLScreenChannel::showToastsBottom() mHiddenToastsNum = 0; for(; it != mToastList.rend(); it++) { - (*it).toast->hide(); + LLToast* toast = it->getToast(); + if (toast) + { + toast->hide(); + } } } } @@ -620,17 +672,31 @@ void LLScreenChannel::showToastsBottom() //-------------------------------------------------------------------------- void LLScreenChannel::showToastsCentre() { - LLRect toast_rect; - S32 bottom = (getRect().mTop - getRect().mBottom)/2 + mToastList[0].toast->getRect().getHeight()/2; + LLToast* toast = mToastList[0].getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + LLRect toast_rect; + S32 bottom = (getRect().mTop - getRect().mBottom)/2 + toast->getRect().getHeight()/2; std::vector<ToastElem>::reverse_iterator it; for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) { - toast_rect = (*it).toast->getRect(); + LLToast* toast = it->getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + toast_rect = toast->getRect(); toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight()); - (*it).toast->setRect(toast_rect); + toast->setRect(toast_rect); - (*it).toast->setVisible(TRUE); + toast->setVisible(TRUE); } } @@ -652,16 +718,29 @@ void LLScreenChannel::showToastsTop() { if(it != mToastList.rbegin()) { - LLToast* toast = (*(it-1)).toast; + LLToast* toast = (it-1)->getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + top = toast->getRect().mBottom - toast->getTopPad(); toast_margin = gSavedSettings.getS32("ToastGap"); } - toast_rect = (*it).toast->getRect(); + LLToast* toast = it->getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + toast_rect = toast->getRect(); toast_rect.setLeftTopAndSize(channel_rect.mRight - toast_rect.getWidth(), top, toast_rect.getWidth(), toast_rect.getHeight()); - (*it).toast->setRect(toast_rect); + toast->setRect(toast_rect); if(floater && floater->overlapsScreenChannel()) { @@ -673,7 +752,7 @@ void LLScreenChannel::showToastsTop() { shift -= floater->getDockControl()->getTongueHeight(); } - (*it).toast->translate(0, shift); + toast->translate(0, shift); } LLRect channel_rect = getChannelRect(); @@ -684,13 +763,13 @@ void LLScreenChannel::showToastsTop() } } - bool stop_showing_toasts = (*it).toast->getRect().mBottom < channel_rect.mBottom; + bool stop_showing_toasts = toast->getRect().mBottom < channel_rect.mBottom; if(!stop_showing_toasts) { if( it != mToastList.rend()-1) { - S32 toast_bottom = (*it).toast->getRect().mBottom - gSavedSettings.getS32("ToastGap"); + S32 toast_bottom = toast->getRect().mBottom - gSavedSettings.getS32("ToastGap"); stop_showing_toasts = toast_bottom < channel_rect.mBottom; } } @@ -704,29 +783,41 @@ void LLScreenChannel::showToastsTop() if(stop_showing_toasts) break; - if( !(*it).toast->getVisible() ) + if (!toast->getVisible()) { // HACK // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts - (*it).toast->setVisible(TRUE); + toast->setVisible(TRUE); } - if(!(*it).toast->hasFocus()) + if (!toast->hasFocus()) { // Fixing Z-order of toasts (EXT-4862) // Next toast will be positioned under this one. - gFloaterView->sendChildToBack((*it).toast); + gFloaterView->sendChildToBack(toast); } } // Dismiss toasts we don't have space for (STORM-391). + std::vector<LLToast*> toasts_to_hide; if(it != mToastList.rend()) { mHiddenToastsNum = 0; for(; it != mToastList.rend(); it++) { - (*it).toast->hide(); + LLToast* toast = it->getToast(); + if (toast) + { + toasts_to_hide.push_back(toast); + } } } + + for (std::vector<LLToast*>::iterator it = toasts_to_hide.begin(), end_it = toasts_to_hide.end(); + it != end_it; + ++it) + { + (*it)->hide(); + } } //-------------------------------------------------------------------------- @@ -827,7 +918,17 @@ void LLNotificationsUI::LLScreenChannel::startToastTimer(LLToast* toast) void LLScreenChannel::hideToastsFromScreen() { for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) - (*it).toast->setVisible(FALSE); + { + LLToast* toast = it->getToast(); + if (toast) + { + toast->setVisible(FALSE); + } + else + { + llwarns << "Attempt to hide a deleted toast." << llendl; + } + } } //-------------------------------------------------------------------------- @@ -836,8 +937,15 @@ void LLScreenChannel::hideToast(const LLUUID& notification_id) std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), notification_id); if(mToastList.end() != it) { - ToastElem te = *it; - te.toast->hide(); + LLToast* toast = it->getToast(); + if (toast) + { + toast->hide(); + } + else + { + llwarns << "Attempt to hide a deleted toast." << llendl; + } } } @@ -845,24 +953,25 @@ void LLScreenChannel::closeHiddenToasts(const Matcher& matcher) { // since we can't guarantee that close toast operation doesn't change mToastList // we collect matched toasts that should be closed into separate list - std::list<ToastElem> toasts; + std::list<LLToast*> toasts; for (std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) { - LLToast * toast = it->toast; + LLToast* toast = it->getToast(); // add to list valid toast that match to provided matcher criteria if (toast != NULL && !toast->isDead() && toast->getNotification() != NULL && !toast->getVisible() && matcher.matches(toast->getNotification())) { - toasts.push_back(*it); + toasts.push_back(toast); } } // close collected toasts - for (std::list<ToastElem>::iterator it = toasts.begin(); it + for (std::list<LLToast*>::iterator it = toasts.begin(); it != toasts.end(); it++) { - it->toast->closeFloater(); + LLToast* toast = *it; + toast->closeFloater(); } } @@ -872,7 +981,7 @@ void LLScreenChannel::removeToastsFromChannel() hideToastsFromScreen(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) { - deleteToast((*it).toast); + deleteToast(it->getToast()); } mToastList.clear(); } @@ -886,9 +995,10 @@ void LLScreenChannel::removeAndStoreAllStorableToasts() hideToastsFromScreen(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();) { - if((*it).toast->getCanBeStored()) + LLToast* toast = it->getToast(); + if(toast && toast->getCanBeStored()) { - storeToast(*(it)); + storeToast(*it); it = mToastList.erase(it); } else @@ -908,9 +1018,10 @@ void LLScreenChannel::removeToastsBySessionID(LLUUID id) hideToastsFromScreen(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();) { - if((*it).toast->getSessionID() == id) + LLToast* toast = it->getToast(); + if(toast && toast->getSessionID() == id) { - deleteToast((*it).toast); + deleteToast(toast); it = mToastList.erase(it); } else @@ -968,5 +1079,5 @@ LLToast* LLScreenChannel::getToastByNotificationID(LLUUID id) if (it == mStoredToastList.end()) return NULL; - return it->toast; + return it->getToast(); } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index c9f8855fe6..56a9cf8b4b 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -117,7 +117,7 @@ public: // get ID of a channel LLUUID getChannelID() { return mID; } - LLHandle<LLScreenChannelBase> getHandle() { mRootHandle.bind(this); return mRootHandle; } + LLHandle<LLScreenChannelBase> getHandle() { return getDerivedHandle<LLScreenChannelBase>(); } protected: void updateRect(); @@ -130,7 +130,6 @@ protected: bool mDisplayToastsAlways; // controls whether a channel shows toasts or not bool mShowToasts; - LLRootHandle<LLScreenChannelBase> mRootHandle; // EToastAlignment mToastAlignment; EChannelAlignment mChannelAlignment; @@ -163,7 +162,7 @@ public: virtual bool matches(const LLNotificationPtr) const = 0; }; - std::list<LLToast*> findToasts(const Matcher& matcher); + std::list<const LLToast*> findToasts(const Matcher& matcher); // Channel's outfit-functions // update channel's size and position in the World View @@ -238,31 +237,39 @@ public: reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } private: - struct ToastElem + class ToastElem { - LLUUID id; - LLToast* toast; + public: + ToastElem(const LLHandle<LLToast>& toast) : mToast(toast) + { + } - ToastElem(LLToast::Params p) : id(p.notif_id) + ToastElem(const ToastElem& toast_elem) : mToast(toast_elem.mToast) { - toast = new LLToast(p); } - ToastElem(const ToastElem& toast_elem) + LLToast* getToast() const { - id = toast_elem.id; - toast = toast_elem.toast; + return mToast.get(); + } + + LLUUID getID() const + { + return mToast.isDead() ? LLUUID() : mToast.get()->getNotificationID(); } bool operator == (const LLUUID &id_op) const { - return (id == id_op); + return (getID() == id_op); } bool operator == (LLPanel* panel_op) const { - return (toast == panel_op); + return (mToast.get() == panel_op); } + + private: + LLHandle<LLToast> mToast; }; // Channel's handlers diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 8d64c8c04f..30400a4c6a 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1360,7 +1360,11 @@ void LLSecAPIBasicHandler::_writeProtectedData() // (even though this file isn't really secure. Perhaps in the future // it may be, however. LLFile::remove(tmp_filename); - throw LLProtectedDataException("Error writing Protected Data Store"); + + // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() + // Decided throwing an exception here was overkill until we figure out why this happens + //throw LLProtectedDataException("Error writing Protected Data Store"); + llinfos << "LLProtectedDataException(Error writing Protected Data Store)" << llendl; } // move the temporary file to the specified file location. @@ -1369,7 +1373,11 @@ void LLSecAPIBasicHandler::_writeProtectedData() (LLFile::rename(tmp_filename, mProtectedDataFilename))) { LLFile::remove(tmp_filename); - throw LLProtectedDataException("Could not overwrite protected data store"); + + // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() + // Decided throwing an exception here was overkill until we figure out why this happens + //throw LLProtectedDataException("Could not overwrite protected data store"); + llinfos << "LLProtectedDataException(Could not overwrite protected data store)" << llendl; } } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 6111255a66..eec2c0a521 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -3051,11 +3051,11 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, // TODO: Make sure you have delete permissions on all of them. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); // attempt to derez into the trash. - LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id); + LLDeRezInfo info(DRD_TRASH, trash_id); LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", packDeRezHeader, packObjectLocalID, - (void*)info, + (void*) &info, SEND_ONLY_ROOTS); // VEFFECT: Delete Object - one effect for all deletes if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) @@ -3745,13 +3745,15 @@ void LLSelectMgr::deselectAllIfTooFar() void LLSelectMgr::selectionSetObjectName(const std::string& name) { + std::string name_copy(name); + // we only work correctly if 1 object is selected. if(mSelectedObjects->getRootObjectCount() == 1) { sendListToRegions("ObjectName", packAgentAndSessionID, packObjectName, - (void*)(new std::string(name)), + (void*)(&name_copy), SEND_ONLY_ROOTS); } else if(mSelectedObjects->getObjectCount() == 1) @@ -3759,20 +3761,22 @@ void LLSelectMgr::selectionSetObjectName(const std::string& name) sendListToRegions("ObjectName", packAgentAndSessionID, packObjectName, - (void*)(new std::string(name)), + (void*)(&name_copy), SEND_INDIVIDUALS); } } void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) { + std::string desc_copy(desc); + // we only work correctly if 1 object is selected. if(mSelectedObjects->getRootObjectCount() == 1) { sendListToRegions("ObjectDescription", packAgentAndSessionID, packObjectDescription, - (void*)(new std::string(desc)), + (void*)(&desc_copy), SEND_ONLY_ROOTS); } else if(mSelectedObjects->getObjectCount() == 1) @@ -3780,7 +3784,7 @@ void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) sendListToRegions("ObjectDescription", packAgentAndSessionID, packObjectDescription, - (void*)(new std::string(desc)), + (void*)(&desc_copy), SEND_INDIVIDUALS); } } @@ -4298,15 +4302,14 @@ void LLSelectMgr::packObjectName(LLSelectNode* node, void* user_data) gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); gMessageSystem->addStringFast(_PREHASH_Name, *name); } - delete name; } // static void LLSelectMgr::packObjectDescription(LLSelectNode* node, void* user_data) { const std::string* desc = (const std::string*)user_data; - if(!desc->empty()) - { + if(desc) + { // Empty (non-null, but zero length) descriptions are OK gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); gMessageSystem->addStringFast(_PREHASH_Description, *desc); diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 038b18afbd..4f9ab318a5 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -78,7 +78,6 @@ static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox"; // // Helpers // - class LLInboxAddedObserver : public LLInventoryCategoryAddedObserver { public: @@ -130,6 +129,11 @@ LLSidepanelInventory::LLSidepanelInventory() LLSidepanelInventory::~LLSidepanelInventory() { + LLLayoutPanel* inbox_layout_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); + + // Save the InventoryMainPanelHeight in settings per account + gSavedPerAccountSettings.setS32("InventoryInboxHeight", inbox_layout_panel->getTargetDim()); + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) { gInventory.removeObserver(mCategoriesObserver); @@ -217,15 +221,22 @@ BOOL LLSidepanelInventory::postBuild() { LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); - // Collapse inbox panel - inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true); - // Set up button states and callbacks LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME); - inbox_button->setToggleState(false); inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this)); + // Get the previous inbox state from "InventoryInboxToggleState" setting. + bool is_inbox_collapsed = !inbox_button->getToggleState(); + + // Restore the collapsed inbox panel state + LLLayoutPanel* inbox_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); + inv_stack->collapsePanel(inbox_panel, is_inbox_collapsed); + if (!is_inbox_collapsed) + { + inbox_panel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight")); + } + // Set the inbox visible based on debug settings (final setting comes from http request below) enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox")); @@ -368,10 +379,19 @@ void LLSidepanelInventory::onToggleInboxBtn() // Expand/collapse the indicated panel inv_stack->collapsePanel(inboxPanel, !inbox_expanded); - if (inbox_expanded && inboxPanel->isInVisibleChain()) + if (inbox_expanded) { - gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); + inboxPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight")); + if (inboxPanel->isInVisibleChain()) + { + gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); + } } + else + { + gSavedPerAccountSettings.setS32("InventoryInboxHeight", inboxPanel->getTargetDim()); + } + } void LLSidepanelInventory::onOpen(const LLSD& key) diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 24cb559fd0..64b82aa0bb 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -94,7 +94,7 @@ BOOL LLSidepanelTaskInfo::postBuild() mPayBtn = getChild<LLButton>("pay_btn"); mPayBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onPayButtonClicked, this)); mBuyBtn = getChild<LLButton>("buy_btn"); - mBuyBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onBuyButtonClicked, this)); + mBuyBtn->setClickedCallback(boost::bind(&handle_buy)); mDetailsBtn = getChild<LLButton>("details_btn"); mDetailsBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onDetailsButtonClicked, this)); @@ -1114,8 +1114,6 @@ void LLSidepanelTaskInfo::doClickAction(U8 click_action) // Set click action back to its old value U8 click_action = 0; LLSelectMgr::getInstance()->selectionGetClickAction(&click_action); -// box->setCurrentByIndex((S32)click_action); - return; } } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 5d196a465f..8e62b79d7f 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1186,6 +1186,7 @@ void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode) //====================================== LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : + mObjectBoxSize(1.f), mState(0), mGeometryBytes(0), mSurfaceArea(0.f), @@ -3647,6 +3648,110 @@ void renderShadowFrusta(LLDrawInfo* params) gGL.setSceneBlendType(LLRender::BT_ALPHA); } +void renderTexelDensity(LLDrawable* drawable) +{ + if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF + || LLViewerTexture::sCheckerBoardImagep.isNull()) + { + return; + } + + LLGLEnable _(GL_BLEND); + //gObjectFullbrightProgram.bind(); + + LLMatrix4 checkerboard_matrix; + S32 discard_level = -1; + + for (S32 f = 0; f < drawable->getNumFaces(); f++) + { + LLFace* facep = drawable->getFace(f); + LLVertexBuffer* buffer = facep->getVertexBuffer(); + LLViewerTexture* texturep = facep->getTexture(); + + if (texturep == NULL) continue; + + switch(LLViewerTexture::sDebugTexelsMode) + { + case LLViewerTexture::DEBUG_TEXELS_CURRENT: + discard_level = -1; + break; + case LLViewerTexture::DEBUG_TEXELS_DESIRED: + { + LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); + discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + break; + } + default: + case LLViewerTexture::DEBUG_TEXELS_FULL: + discard_level = 0; + break; + } + + checkerboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + + gGL.getTexUnit(0)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*)&checkerboard_matrix.mMatrix); + + if (buffer && (facep->getGeomCount() >= 3)) + { + buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + U16 start = facep->getGeomStart(); + U16 end = start + facep->getGeomCount()-1; + U32 count = facep->getIndicesCount(); + U16 offset = facep->getIndicesStart(); + buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + + //S32 num_textures = llmax(1, (S32)params->mTextureList.size()); + + //for (S32 i = 0; i < num_textures; i++) + //{ + // LLViewerTexture* texturep = params->mTextureList.empty() ? params->mTexture.get() : params->mTextureList[i].get(); + // if (texturep == NULL) continue; + + // LLMatrix4 checkboard_matrix; + // S32 discard_level = -1; + // switch(LLViewerTexture::sDebugTexelsMode) + // { + // case LLViewerTexture::DEBUG_TEXELS_CURRENT: + // discard_level = -1; + // break; + // case LLViewerTexture::DEBUG_TEXELS_DESIRED: + // { + // LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); + // discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + // break; + // } + // default: + // case LLViewerTexture::DEBUG_TEXELS_FULL: + // discard_level = 0; + // break; + // } + + // checkboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + // gGL.getTexUnit(i)->activate(); + + // glMatrixMode(GL_TEXTURE); + // glPushMatrix(); + // glLoadIdentity(); + // //gGL.matrixMode(LLRender::MM_TEXTURE); + // glLoadMatrixf((GLfloat*) checkboard_matrix.mMatrix); + + // gGL.getTexUnit(i)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + + // pushVerts(params, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL ); + + // glPopMatrix(); + // glMatrixMode(GL_MODELVIEW); + // //gGL.matrixMode(LLRender::MM_MODELVIEW); + //} +} + void renderLights(LLDrawable* drawablep) { @@ -4042,6 +4147,10 @@ public: { renderComplexityDisplay(drawable); } + if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + renderTexelDensity(drawable); + } LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); @@ -4291,7 +4400,8 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_AGENT_TARGET | //LLPipeline::RENDER_DEBUG_BUILD_QUEUE | LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | - LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)) + LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY | + LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) { return; } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 6c14ecf452..1a93145cc5 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -378,6 +378,8 @@ public: LLVector4a mObjectBounds[2]; // bounding box (center, size) of objects in this node LLVector4a mViewAngle; LLVector4a mLastUpdateViewAngle; + + F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3() private: U32 mCurUpdatingTime ; diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index c588bd8fb4..07d2f1ad6f 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -272,6 +272,7 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin speakerp->mStatus = status; mSpeakers.insert(std::make_pair(speakerp->mID, speakerp)); mSpeakersSorted.push_back(speakerp); + LL_DEBUGS("Speakers") << "Added speaker " << id << llendl; fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add"); } else @@ -290,6 +291,10 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin speakerp->lookupName(); } } + else + { + LL_WARNS("Speakers") << "Speaker " << id << " not found" << llendl; + } } mSpeakerDelayRemover->unsetActionTimer(speakerp->mID); @@ -354,6 +359,7 @@ void LLSpeakerMgr::update(BOOL resort_ok) if (moderator_muted_voice != speakerp->mModeratorMutedVoice) { speakerp->mModeratorMutedVoice = moderator_muted_voice; + LL_DEBUGS("Speakers") << (speakerp->mModeratorMutedVoice? "Muted" : "Umuted") << " speaker " << speaker_id<< llendl; speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp)); } @@ -484,6 +490,7 @@ bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id) } } + LL_DEBUGS("Speakers") << "Removed speaker " << speaker_id << llendl; fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove"); update(TRUE); @@ -595,7 +602,10 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers) speaker_it->second["mutes"]["text"]; // Fire event only if moderator changed if ( is_moderator != speakerp->mIsModerator ) + { + LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << llendl; fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); + } } } } @@ -665,7 +675,10 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) speakerp->mIsModerator = agent_info["is_moderator"]; // Fire event only if moderator changed if ( is_moderator != speakerp->mIsModerator ) + { + LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << llendl; fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); + } } if (agent_info.has("mutes")) @@ -857,6 +870,7 @@ void LLActiveSpeakerMgr::updateSpeakerList() // always populate from active voice channel if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false { + LL_DEBUGS("Speakers") << "Removed all speakers" << llendl; fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear"); mSpeakers.clear(); mSpeakersSorted.clear(); diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 35f2ee7056..b9358cf37c 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -208,6 +208,8 @@ private: class LLSpeakerMgr : public LLOldEvents::LLObservable { + LOG_CLASS(LLSpeakerMgr); + public: LLSpeakerMgr(LLVoiceChannel* channelp); virtual ~LLSpeakerMgr(); @@ -271,6 +273,8 @@ protected: class LLIMSpeakerMgr : public LLSpeakerMgr { + LOG_CLASS(LLIMSpeakerMgr); + public: LLIMSpeakerMgr(LLVoiceChannel* channel); @@ -320,6 +324,8 @@ protected: class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr> { + LOG_CLASS(LLActiveSpeakerMgr); + public: LLActiveSpeakerMgr(); protected: @@ -328,6 +334,7 @@ protected: class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr> { + LOG_CLASS(LLLocalSpeakerMgr); public: LLLocalSpeakerMgr(); ~LLLocalSpeakerMgr (); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 3923b4510a..6b0fc26db7 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -240,6 +240,7 @@ static bool mLoginStatePastUI = false; boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState")); boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener()); +boost::scoped_ptr<LLViewerStats::PhaseMap> LLStartUp::sPhases(new LLViewerStats::PhaseMap); // // local function declaration @@ -880,7 +881,6 @@ bool idle_startup() LLFile::mkdir(gDirUtilp->getLindenUserDir()); // Set PerAccountSettingsFile to the default value. - std::string per_account_settings_file = LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount"); gSavedSettings.setString("PerAccountSettingsFile", gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount"))); @@ -2706,7 +2706,10 @@ void LLStartUp::setStartupState( EStartupState state ) LL_INFOS("AppInit") << "Startup state changing from " << getStartupStateString() << " to " << startupStateToString(state) << LL_ENDL; + + sPhases->stopPhase(getStartupStateString()); gStartupState = state; + sPhases->startPhase(getStartupStateString()); postStartupState(); } diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 0a18ef1b2d..3754aaf966 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -34,6 +34,8 @@ class LLEventPump; class LLStartupListener; class LLSLURL; +#include "llviewerstats.h" + // functions bool idle_startup(); void release_start_screen(); @@ -113,6 +115,7 @@ public: static bool startLLProxy(); // Initialize the SOCKS 5 proxy + static LLViewerStats::PhaseMap& getPhases() { return *sPhases; } private: static LLSLURL sStartSLURL; @@ -120,6 +123,7 @@ private: static EStartupState gStartupState; // Do not set directly, use LLStartup::setStartupState static boost::scoped_ptr<LLEventPump> sStateWatcher; static boost::scoped_ptr<LLStartupListener> sListener; + static boost::scoped_ptr<LLViewerStats::PhaseMap> sPhases; }; diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 6f6d5dbf12..467115c928 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -55,6 +55,9 @@ using namespace LLVOAvatarDefines; static const S32 BAKE_UPLOAD_ATTEMPTS = 7; static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt +// runway consolidate +extern std::string self_av_string(); + class LLTexLayerInfo { friend class LLTexLayer; @@ -494,7 +497,6 @@ void LLTexLayerSetBuffer::doUpload() } LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C; - compressedImage->setRate(0.f); const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask) if (compressedImage->encode(baked_image, comment_text)) { @@ -577,7 +579,7 @@ void LLTexLayerSetBuffer::doUpload() args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); args["RESOLUTION"] = lod_str; LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); - llinfos << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; } } else @@ -631,7 +633,7 @@ void LLTexLayerSetBuffer::doUpdate() args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); args["RESOLUTION"] = lod_str; LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args); - llinfos << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << llendl; + LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL; } } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index de22f2ae6b..ed9faa0706 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -67,6 +67,9 @@ #include "lluictrlfactory.h" #include "lltrans.h" +#include "llradiogroup.h" +#include "llfloaterreg.h" +#include "lllocalbitmaps.h" static const S32 HPAD = 4; static const S32 VPAD = 4; @@ -78,6 +81,8 @@ static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; static const F32 CONTEXT_FADE_TIME = 0.08f; +static const S32 LOCAL_TRACKING_ID_COLUMN = 1; + //static const char CURRENT_IMAGE_NAME[] = "Current Texture"; //static const char WHITE_IMAGE_NAME[] = "Blank Texture"; //static const char NO_IMAGE_NAME[] = "None"; @@ -142,6 +147,12 @@ public: static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); void onTextureSelect( const LLTextureEntry& te ); + static void onModeSelect(LLUICtrl* ctrl, void *userdata); + static void onBtnAdd(void* userdata); + static void onBtnRemove(void* userdata); + static void onBtnUpload(void* userdata); + static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata); + protected: LLPointer<LLViewerTexture> mTexturep; LLTextureCtrl* mOwner; @@ -169,8 +180,10 @@ protected: BOOL mNoCopyTextureSelected; F32 mContextConeOpacity; LLSaveFolderState mSavedFolderState; - BOOL mSelectedItemPinned; + + LLRadioGroup* mModeSelector; + LLScrollListCtrl* mLocalScrollCtrl; }; LLFloaterTexturePicker::LLFloaterTexturePicker( @@ -437,6 +450,17 @@ BOOL LLFloaterTexturePicker::postBuild() mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); } + mModeSelector = getChild<LLRadioGroup>("mode_selection"); + mModeSelector->setCommitCallback(onModeSelect, this); + mModeSelector->setSelectedIndex(0, 0); + + childSetAction("l_add_btn", LLFloaterTexturePicker::onBtnAdd, this); + childSetAction("l_rem_btn", LLFloaterTexturePicker::onBtnRemove, this); + childSetAction("l_upl_btn", LLFloaterTexturePicker::onBtnUpload, this); + + mLocalScrollCtrl = getChild<LLScrollListCtrl>("l_name_list"); + mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this); + LLLocalBitmapMgr::feedScrollList(mLocalScrollCtrl); mNoCopyTextureSelected = FALSE; @@ -464,7 +488,6 @@ BOOL LLFloaterTexturePicker::postBuild() // virtual void LLFloaterTexturePicker::draw() { - S32 floater_header_size = getHeaderHeight(); if (mOwner) { // draw cone of context pointing back to texture swatch @@ -554,10 +577,7 @@ void LLFloaterTexturePicker::draw() } // Border - LLRect border( BORDER_PAD, - getRect().getHeight() - floater_header_size - BORDER_PAD, - ((getMinWidth() / 2) - TEXTURE_INVENTORY_PADDING - HPAD) - BORDER_PAD, - BORDER_PAD + FOOTER_HEIGHT + (getRect().getHeight() - getMinHeight())); + LLRect border = getChildView("preview_widget")->getRect(); gl_rect_2d( border, LLColor4::black, FALSE ); @@ -748,7 +768,15 @@ void LLFloaterTexturePicker::onBtnSelect(void* userdata) LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; if (self->mOwner) { - self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT); + LLUUID local_id = LLUUID::null; + + if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty()) + { + LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID(); + local_id = LLLocalBitmapMgr::getWorldID(temp_id); + } + + self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT, local_id); } self->closeFloater(); } @@ -792,6 +820,112 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem } // static +void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + bool mode = (self->mModeSelector->getSelectedIndex() == 0); + + self->getChild<LLButton>("Default")->setVisible(mode); + self->getChild<LLButton>("Blank")->setVisible(mode); + self->getChild<LLButton>("None")->setVisible(mode); + self->getChild<LLButton>("Pipette")->setVisible(mode); + self->getChild<LLFilterEditor>("inventory search editor")->setVisible(mode); + self->getChild<LLInventoryPanel>("inventory panel")->setVisible(mode); + + /*self->getChild<LLCheckBox>("show_folders_check")->setVisible(mode); + no idea under which conditions the above is even shown, needs testing. */ + + self->getChild<LLButton>("l_add_btn")->setVisible(!mode); + self->getChild<LLButton>("l_rem_btn")->setVisible(!mode); + self->getChild<LLButton>("l_upl_btn")->setVisible(!mode); + self->getChild<LLScrollListCtrl>("l_name_list")->setVisible(!mode); +} + +// static +void LLFloaterTexturePicker::onBtnAdd(void* userdata) +{ + if (LLLocalBitmapMgr::addUnit() == true) + { + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + LLLocalBitmapMgr::feedScrollList(self->mLocalScrollCtrl); + } +} + +// static +void LLFloaterTexturePicker::onBtnRemove(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected(); + + if (!selected_items.empty()) + { + for(std::vector<LLScrollListItem*>::iterator iter = selected_items.begin(); + iter != selected_items.end(); iter++) + { + LLScrollListItem* list_item = *iter; + if (list_item) + { + LLUUID tracking_id = list_item->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID(); + LLLocalBitmapMgr::delUnit(tracking_id); + } + } + + self->getChild<LLButton>("l_rem_btn")->setEnabled(false); + self->getChild<LLButton>("l_upl_btn")->setEnabled(false); + LLLocalBitmapMgr::feedScrollList(self->mLocalScrollCtrl); + } + +} + +// static +void LLFloaterTexturePicker::onBtnUpload(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected(); + + if (selected_items.empty()) + { + return; + } + + /* currently only allows uploading one by one, picks the first item from the selection list. (not the vector!) + in the future, it might be a good idea to check the vector size and if more than one units is selected - opt for multi-image upload. */ + + LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN); + std::string filename = LLLocalBitmapMgr::getFilename(tracking_id); + + if (!filename.empty()) + { + LLFloaterReg::showInstance("upload_image", LLSD(filename)); + } + +} + +//static +void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected(); + bool has_selection = !selected_items.empty(); + + self->getChild<LLButton>("l_rem_btn")->setEnabled(has_selection); + self->getChild<LLButton>("l_upl_btn")->setEnabled(has_selection && (selected_items.size() < 2)); + /* since multiple-localbitmap upload is not implemented, upl button gets disabled if more than one is selected. */ + + if (has_selection) + { + LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN); + LLUUID inworld_id = LLLocalBitmapMgr::getWorldID(tracking_id); + self->mOwner->setImageAssetID(inworld_id); + + if (self->childGetValue("apply_immediate_check").asBoolean()) + { + self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE, inworld_id); + } + } +} + +// static void LLFloaterTexturePicker::onShowFolders(LLUICtrl* ctrl, void *user_data) { LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; @@ -922,13 +1056,20 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p) S32 image_top = getRect().getHeight(); S32 image_bottom = BTN_HEIGHT_SMALL; S32 image_middle = (image_top + image_bottom) / 2; - S32 line_height = llround(LLFontGL::getFontSansSerifSmall()->getLineHeight()); + S32 line_height = LLFontGL::getFontSansSerifSmall()->getLineHeight(); LLTextBox::Params tentative_label_p(p.multiselect_text); tentative_label_p.name("Multiple"); tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 )); tentative_label_p.follows.flags(FOLLOWS_ALL); mTentativeLabel = LLUICtrlFactory::create<LLTextBox> (tentative_label_p); + + // It is no longer possible to associate a style with a textbox, so it has to be done in this fashion + LLStyle::Params style_params; + style_params.color = LLColor4::white; + + mTentativeLabel->setText(LLTrans::getString("multiple_textures"), style_params); + mTentativeLabel->setHAlign(LLFontGL::HCENTER); addChild( mTentativeLabel ); LLRect border_rect = getLocalRect(); @@ -1126,7 +1267,7 @@ void LLTextureCtrl::onFloaterClose() mFloaterHandle.markDead(); } -void LLTextureCtrl::onFloaterCommit(ETexturePickOp op) +void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) { LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); @@ -1139,14 +1280,24 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op) // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. else if (mCommitOnSelection || op == TEXTURE_SELECT) mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - - if( floaterp->isDirty() ) + + if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work. { setTentative( FALSE ); - mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); - lldebugs << "mImageItemID: " << mImageItemID << llendl; - mImageAssetID = floaterp->getAssetID(); - lldebugs << "mImageAssetID: " << mImageAssetID << llendl; + + if (id.notNull()) + { + mImageItemID = id; + mImageAssetID = id; + } + else + { + mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); + lldebugs << "mImageItemID: " << mImageItemID << llendl; + mImageAssetID = floaterp->getAssetID(); + lldebugs << "mImageAssetID: " << mImageAssetID << llendl; + } + if (op == TEXTURE_SELECT && mOnSelectCallback) { mOnSelectCallback( this, LLSD() ); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index b1312d641f..3abe84dcc3 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -157,7 +157,7 @@ public: void closeDependentFloater(); void onFloaterClose(); - void onFloaterCommit(ETexturePickOp op); + void onFloaterCommit(ETexturePickOp op, LLUUID id = LLUUID::null); // This call is returned when a drag is detected. Your callback // should return TRUE if the drag is acceptable. diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index f18aa8b4e6..e2af497a7d 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -52,12 +52,20 @@ #include "llviewerstats.h" #include "llviewerassetstats.h" #include "llworld.h" +#include "llsdutil.h" +#include "llstartup.h" +#include "llviewerstats.h" + +bool LLTextureFetchDebugger::sDebuggerEnabled = false ; +LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); +LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128); ////////////////////////////////////////////////////////////////////////////// class LLTextureFetchWorker : public LLWorkerClass { friend class LLTextureFetch; friend class HTTPGetResponder; + friend class LLTextureFetchDebugger; private: class CacheReadResponder : public LLTextureCache::ReadResponder @@ -242,6 +250,8 @@ private: S32 mDecodedDiscard; LLFrameTimer mRequestedTimer; LLFrameTimer mFetchTimer; + LLTimer mCacheReadTimer; + F32 mCacheReadTime; LLTextureCache::handle_t mCacheReadHandle; LLTextureCache::handle_t mCacheWriteHandle; U8* mBuffer; @@ -258,6 +268,7 @@ private: BOOL mNeedsAux; BOOL mHaveAllData; BOOL mInLocalCache; + BOOL mInCache; bool mCanUseHTTP ; bool mCanUseNET ; //can get from asset server. S32 mHTTPFailCount; @@ -653,6 +664,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mRequestedDiscard(-1), mLoadedDiscard(-1), mDecodedDiscard(-1), + mCacheReadTime(0.f), mCacheReadHandle(LLTextureCache::nullHandle()), mCacheWriteHandle(LLTextureCache::nullHandle()), mBuffer(NULL), @@ -669,6 +681,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mNeedsAux(FALSE), mHaveAllData(FALSE), mInLocalCache(FALSE), + mInCache(FALSE), mCanUseHTTP(true), mHTTPFailCount(0), mRetryAttempt(0), @@ -838,6 +851,8 @@ void LLTextureFetchWorker::startWork(S32 param) // Called from LLWorkerThread::processRequest() bool LLTextureFetchWorker::doWork(S32 param) { + static const F32 FETCHING_TIMEOUT = 120.f;//seconds + LLMutexLock lock(&mWorkMutex); if ((mFetcher->isQuitting() || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) @@ -896,6 +911,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mCacheReadHandle = LLTextureCache::nullHandle(); mCacheWriteHandle = LLTextureCache::nullHandle(); mState = LOAD_FROM_TEXTURE_CACHE; + mInCache = FALSE; mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; @@ -926,6 +942,7 @@ bool LLTextureFetchWorker::doWork(S32 param) CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority, offset, size, responder); + mCacheReadTimer.reset(); } else if (mUrl.empty()) { @@ -934,6 +951,7 @@ bool LLTextureFetchWorker::doWork(S32 param) CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, offset, size, responder); + mCacheReadTimer.reset(); } else if(mCanUseHTTP) { @@ -982,11 +1000,12 @@ bool LLTextureFetchWorker::doWork(S32 param) llassert_always(mFormattedImage->getDataSize() > 0); mLoadedDiscard = mDesiredDiscard; mState = DECODE_IMAGE; + mInCache = TRUE; mWriteToCacheState = NOT_WRITE ; LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight()) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; - // fall through + LLTextureFetch::sCacheHitRate.addValue(100.f); } else { @@ -1002,6 +1021,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mState = LOAD_FROM_NETWORK; } // fall through + LLTextureFetch::sCacheHitRate.addValue(0.f); } } @@ -1177,6 +1197,8 @@ bool LLTextureFetchWorker::doWork(S32 param) bool res = false; if (!mUrl.empty()) { + mRequestedTimer.reset(); + mLoaded = FALSE; mGetStatus = 0; mGetReason.clear(); @@ -1335,6 +1357,13 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { + if(FETCHING_TIMEOUT < mRequestedTimer.getElapsedTimeF32()) + { + //timeout, abort. + mState = DONE; + return true; + } + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return false; } @@ -1396,6 +1425,11 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mDecoded) { + if(mFetcher->getFetchDebugger() && !mInLocalCache) + { + mFetcher->getFetchDebugger()->addHistoryEntry(this); + } + if (mDecodedDiscard < 0) { LL_DEBUGS("Texture") << mID << ": Failed to Decode." << LL_ENDL; @@ -1780,6 +1814,7 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag mDecoded = TRUE; // llinfos << mID << " : DECODE COMPLETE " << llendl; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + mCacheReadTime = mCacheReadTimer.getElapsedTimeF32(); } ////////////////////////////////////////////////////////////////////////////// @@ -1824,11 +1859,18 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHTTPTextureBits(0), mTotalHTTPRequests(0), mCurlGetRequest(NULL), - mQAMode(qa_mode) + mQAMode(qa_mode), + mFetchDebugger(NULL) { mCurlPOSTRequestCount = 0; mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); + + LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); + if(LLTextureFetchDebugger::isEnabled()) + { + mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ; + } } LLTextureFetch::~LLTextureFetch() @@ -1843,11 +1885,17 @@ LLTextureFetch::~LLTextureFetch() } // ~LLQueuedThread() called here + + delete mFetchDebugger; } bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) { + if(mFetcherLocked) + { + return false; + } if (mDebugPause) { return false; @@ -2092,6 +2140,11 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, discard_level = worker->mDecodedDiscard; raw = worker->mRawImage; aux = worker->mAuxImage; + F32 cache_read_time = worker->mCacheReadTime; + if (cache_read_time != 0.f) + { + sCacheReadLatency.addValue(cache_read_time * 1000.f); + } res = true; LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL; worker->unlockWorkMutex(); @@ -2222,7 +2275,13 @@ S32 LLTextureFetch::update(F32 max_time_ms) if (!mDebugPause) { - sendRequestListToSimulators(); + // this is the startup state when send_complete_agent_movement() message is sent. + // Before this, the RequestImages message sent by sendRequestListToSimulators + // won't work so don't bother trying + if (LLStartUp::getStartupState() > STATE_AGENT_SEND) + { + sendRequestListToSimulators(); + } } if (!mThreaded) @@ -2258,6 +2317,11 @@ void LLTextureFetch::startThread() { // Construct mCurlGetRequest from Worker Thread mCurlGetRequest = new LLCurlRequest(); + + if(mFetchDebugger) + { + mFetchDebugger->setCurlGetRequest(mCurlGetRequest); + } } // WORKER THREAD @@ -2266,6 +2330,10 @@ void LLTextureFetch::endThread() // Destroy mCurlGetRequest from Worker Thread delete mCurlGetRequest; mCurlGetRequest = NULL; + if(mFetchDebugger) + { + mFetchDebugger->setCurlGetRequest(NULL); + } } // WORKER THREAD @@ -2803,7 +2871,6 @@ void LLTextureFetch::cmdDoWork() } } - ////////////////////////////////////////////////////////////////////////////// // Private (anonymous) class methods implementing the command scheme. @@ -2959,7 +3026,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // In QA mode, Metrics submode, log the result for ease of testing if (fetcher->isQAMode()) { - LL_INFOS("Textures") << merged_llsd << LL_ENDL; + LL_INFOS("Textures") << ll_pretty_print_sd(merged_llsd) << LL_ENDL; } gViewerAssetStatsThread1->reset(); @@ -3007,5 +3074,659 @@ truncate_viewer_metrics(int max_regions, LLSD & metrics) } // end of anonymous namespace +/////////////////////////////////////////////////////////////////////////////////////////// +//Start LLTextureFetchDebugger +/////////////////////////////////////////////////////////////////////////////////////////// +//--------------------- +class LLDebuggerCacheReadResponder : public LLTextureCache::ReadResponder +{ +public: + LLDebuggerCacheReadResponder(LLTextureFetchDebugger* debugger, S32 id, LLImageFormatted* image) + : mDebugger(debugger), mID(id) + { + setImage(image); + } + virtual void completed(bool success) + { + mDebugger->callbackCacheRead(mID, success, mFormattedImage, mImageSize, mImageLocal); + } +private: + LLTextureFetchDebugger* mDebugger; + S32 mID; +}; + +class LLDebuggerCacheWriteResponder : public LLTextureCache::WriteResponder +{ +public: + LLDebuggerCacheWriteResponder(LLTextureFetchDebugger* debugger, S32 id) + : mDebugger(debugger), mID(id) + { + } + virtual void completed(bool success) + { + mDebugger->callbackCacheWrite(mID, success); + } +private: + LLTextureFetchDebugger* mDebugger; + S32 mID; +}; + +class LLDebuggerDecodeResponder : public LLImageDecodeThread::Responder +{ +public: + LLDebuggerDecodeResponder(LLTextureFetchDebugger* debugger, S32 id) + : mDebugger(debugger), mID(id) + { + } + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) + { + mDebugger->callbackDecoded(mID, success, raw, aux); + } +private: + LLTextureFetchDebugger* mDebugger; + S32 mID; +}; + +class LLDebuggerHTTPResponder : public LLCurl::Responder +{ +public: + LLDebuggerHTTPResponder(LLTextureFetchDebugger* debugger, S32 index) + : mDebugger(debugger), mIndex(index) + { + } + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + bool success = false; + bool partial = false; + if (HTTP_OK <= status && status < HTTP_MULTIPLE_CHOICES) + { + success = true; + if (HTTP_PARTIAL_CONTENT == status) // partial information + { + partial = true; + } + } + if (!success) + { + llinfos << "Fetch Debugger : CURL GET FAILED, index = " << mIndex << ", status:" << status << " reason:" << reason << llendl; + } + mDebugger->callbackHTTP(mIndex, channels, buffer, partial, success); + } + virtual bool followRedir() + { + return true; + } +private: + LLTextureFetchDebugger* mDebugger; + S32 mIndex; +}; + +LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) : + mFetcher(fetcher), + mTextureCache(cache), + mImageDecodeThread(imagedecodethread), + mCurlGetRequest(NULL) +{ + init(); +} + +LLTextureFetchDebugger::~LLTextureFetchDebugger() +{ + mFetchingHistory.clear(); + stopDebug(); +} + +void LLTextureFetchDebugger::init() +{ + mState = IDLE; + + mCacheReadTime = -1.f; + mCacheWriteTime = -1.f; + mDecodingTime = -1.f; + mHTTPTime = -1.f; + mGLCreationTime = -1.f; + mTotalFetchingTime = 0.f; + mRefetchVisCacheTime = -1.f; + mRefetchVisHTTPTime = -1.f; + + mNumFetchedTextures = 0; + mNumCacheHits = 0; + mNumVisibleFetchedTextures = 0; + mNumVisibleFetchingRequests = 0; + mFetchedData = 0; + mDecodedData = 0; + mVisibleFetchedData = 0; + mVisibleDecodedData = 0; + mRenderedData = 0; + mRenderedDecodedData = 0; + mFetchedPixels = 0; + mRenderedPixels = 0; + mRefetchedData = 0; + mRefetchedPixels = 0; + + mFreezeHistory = FALSE; +} + +void LLTextureFetchDebugger::startDebug() +{ + //lock the fetcher + mFetcher->lockFetcher(true); + mFreezeHistory = TRUE; + + //clear the current fetching queue + gTextureList.clearFetchingRequests(); + + //wait for all works to be done + while(1) + { + S32 pending = 0; + pending += LLAppViewer::getTextureCache()->update(1); + pending += LLAppViewer::getImageDecodeThread()->update(1); + pending += LLAppViewer::getTextureFetch()->update(1); + if(!pending) + { + break; + } + } + + //collect statistics + mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; + + std::set<LLUUID> fetched_textures; + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size; i++) + { + bool in_list = true; + if(fetched_textures.find(mFetchingHistory[i].mID) == fetched_textures.end()) + { + fetched_textures.insert(mFetchingHistory[i].mID); + in_list = false; + } + + LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(mFetchingHistory[i].mID); + if(tex && tex->isJustBound()) //visible + { + if(!in_list) + { + mNumVisibleFetchedTextures++; + } + mNumVisibleFetchingRequests++; + + mVisibleFetchedData += mFetchingHistory[i].mFetchedSize; + mVisibleDecodedData += mFetchingHistory[i].mDecodedSize; + + if(tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel) + { + mRenderedData += mFetchingHistory[i].mFetchedSize; + mRenderedDecodedData += mFetchingHistory[i].mDecodedSize; + mRenderedPixels += tex->getWidth() * tex->getHeight(); + } + } + } + + mNumFetchedTextures = fetched_textures.size(); +} + +void LLTextureFetchDebugger::stopDebug() +{ + //clear the current debug work + S32 size = mFetchingHistory.size(); + switch(mState) + { + case READ_CACHE: + for(S32 i = 0 ; i < size; i++) + { + if (mFetchingHistory[i]. mCacheHandle != LLTextureCache::nullHandle()) + { + mTextureCache->readComplete(mFetchingHistory[i].mCacheHandle, true); + } + } + break; + case WRITE_CACHE: + for(S32 i = 0 ; i < size; i++) + { + if (mFetchingHistory[i].mCacheHandle != LLTextureCache::nullHandle()) + { + mTextureCache->writeComplete(mFetchingHistory[i].mCacheHandle, true); + } + } + break; + case DECODING: + break; + case HTTP_FETCHING: + break; + case GL_TEX: + break; + default: + break; + } + + while(1) + { + if(update()) + { + break; + } + } + + //unlock the fetcher + mFetcher->lockFetcher(false); + mFreezeHistory = FALSE; + mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32(); //reset +} + +//called in the main thread and when the fetching queue is empty +void LLTextureFetchDebugger::clearHistory() +{ + mFetchingHistory.clear(); + init(); +} + +void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker) +{ + if(mFreezeHistory) + { + mRefetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); + mRefetchedData += worker->mFormattedImage->getDataSize(); + return; + } + + if(worker->mInCache) + { + mNumCacheHits++; + } + mFetchedData += worker->mFormattedImage->getDataSize(); + mDecodedData += worker->mRawImage->getDataSize(); + mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); + + mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize())); + //mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mHaveAllData ? 0 : worker->mLoadedDiscard, worker->mFormattedImage->getComponents(), + //worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize())); +} + +void LLTextureFetchDebugger::lockCache() +{ +} + +void LLTextureFetchDebugger::unlockCache() +{ +} + +void LLTextureFetchDebugger::debugCacheRead() +{ + lockCache(); + llassert_always(mState == IDLE); + mTimer.reset(); + mState = READ_CACHE; + + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + mFetchingHistory[i].mFormattedImage = NULL; + mFetchingHistory[i].mCacheHandle = mTextureCache->readFromCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 0, mFetchingHistory[i].mFetchedSize, + new LLDebuggerCacheReadResponder(this, i, mFetchingHistory[i].mFormattedImage)); + } +} + +void LLTextureFetchDebugger::clearCache() +{ + S32 size = mFetchingHistory.size(); + { + std::set<LLUUID> deleted_list; + for(S32 i = 0 ; i < size ; i++) + { + if(deleted_list.find(mFetchingHistory[i].mID) == deleted_list.end()) + { + deleted_list.insert(mFetchingHistory[i].mID); + mTextureCache->removeFromCache(mFetchingHistory[i].mID); + } + } + } +} + +void LLTextureFetchDebugger::debugCacheWrite() +{ + //remove from cache + clearCache(); + + lockCache(); + llassert_always(mState == IDLE); + mTimer.reset(); + mState = WRITE_CACHE; + + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + if(mFetchingHistory[i].mFormattedImage.notNull()) + { + mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, + mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize, + mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1, + new LLDebuggerCacheWriteResponder(this, i)); + } + } +} + +void LLTextureFetchDebugger::lockDecoder() +{ +} + +void LLTextureFetchDebugger::unlockDecoder() +{ +} + +void LLTextureFetchDebugger::debugDecoder() +{ + lockDecoder(); + llassert_always(mState == IDLE); + mTimer.reset(); + mState = DECODING; + + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + if(mFetchingHistory[i].mFormattedImage.isNull()) + { + continue; + } + + mImageDecodeThread->decodeImage(mFetchingHistory[i].mFormattedImage, LLWorkerThread::PRIORITY_NORMAL, + mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mNeedsAux, + new LLDebuggerDecodeResponder(this, i)); + } +} + +void LLTextureFetchDebugger::debugHTTP() +{ + llassert_always(mState == IDLE); + + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + { + llinfos << "Fetch Debugger : Current region undefined. Cannot fetch textures through HTTP." << llendl; + return; + } + + mHTTPUrl = region->getHttpUrl(); + if (mHTTPUrl.empty()) + { + llinfos << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << llendl; + return; + } + + mTimer.reset(); + mState = HTTP_FETCHING; + + S32 size = mFetchingHistory.size(); + for (S32 i = 0 ; i < size ; i++) + { + mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE; + mFetchingHistory[i].mCurlReceivedSize = 0; + mFetchingHistory[i].mHTTPFailCount = 0; + } + mNbCurlRequests = 0; + mNbCurlCompleted = 0; + + fillCurlQueue(); +} + +S32 LLTextureFetchDebugger::fillCurlQueue() +{ + if (mNbCurlRequests == 24) + return mNbCurlRequests; + + S32 size = mFetchingHistory.size(); + for (S32 i = 0 ; i < size ; i++) + { + if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE) + continue; + std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[i].mID.asString().c_str(); + S32 requestedSize = mFetchingHistory[i].mRequestedSize; + // We request the whole file if the size was not set. + requestedSize = llmax(0,requestedSize); + // We request the whole file if the size was set to an absurdly high value (meaning all file) + requestedSize = (requestedSize == 33554432 ? 0 : requestedSize); + std::vector<std::string> headers; + headers.push_back("Accept: image/x-j2c"); + bool res = mCurlGetRequest->getByteRange(texture_url, headers, 0, requestedSize, new LLDebuggerHTTPResponder(this, i)); + if (res) + { + mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS; + mNbCurlRequests++; + // Hack + if (mNbCurlRequests == 24) + break; + } + else + { + break; + } + } + //llinfos << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << llendl; + return mNbCurlRequests; +} + +void LLTextureFetchDebugger::debugGLTextureCreation() +{ + llassert_always(mState == IDLE); + mState = GL_TEX; + std::vector<LLViewerFetchedTexture*> tex_list; + + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + if(mFetchingHistory[i].mRawImage.notNull()) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ; + if(tex && !tex->isForSculptOnly()) + { + tex->destroyGLTexture() ; + tex_list.push_back(tex); + } + } + } + + mTimer.reset(); + S32 j = 0 ; + S32 size1 = tex_list.size(); + for(S32 i = 0 ; i < size && j < size1; i++) + { + if(mFetchingHistory[i].mRawImage.notNull()) + { + if(mFetchingHistory[i].mID == tex_list[j]->getID()) + { + tex_list[j]->createGLTexture(mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mRawImage, 0, TRUE, tex_list[j]->getBoostLevel()); + j++; + } + } + } + + mGLCreationTime = mTimer.getElapsedTimeF32() ; + return; +} + +//clear fetching results of all textures. +void LLTextureFetchDebugger::clearTextures() +{ + S32 size = mFetchingHistory.size(); + for(S32 i = 0 ; i < size ; i++) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ; + if(tex) + { + tex->clearFetchedResults() ; + } + } +} + +void LLTextureFetchDebugger::debugRefetchVisibleFromCache() +{ + llassert_always(mState == IDLE); + mState = REFETCH_VIS_CACHE; + + clearTextures(); + + mTimer.reset(); + mFetcher->lockFetcher(false); +} + +void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP() +{ + llassert_always(mState == IDLE); + mState = REFETCH_VIS_HTTP; + + clearCache(); + clearTextures(); + + mTimer.reset(); + mFetcher->lockFetcher(false); +} + +bool LLTextureFetchDebugger::update() +{ + switch(mState) + { + case READ_CACHE: + if(!mTextureCache->update(1)) + { + mCacheReadTime = mTimer.getElapsedTimeF32() ; + mState = IDLE; + unlockCache(); + } + break; + case WRITE_CACHE: + if(!mTextureCache->update(1)) + { + mCacheWriteTime = mTimer.getElapsedTimeF32() ; + mState = IDLE; + unlockCache(); + } + break; + case DECODING: + if(!mImageDecodeThread->update(1)) + { + mDecodingTime = mTimer.getElapsedTimeF32() ; + mState = IDLE; + unlockDecoder(); + } + break; + case HTTP_FETCHING: + mCurlGetRequest->process(); + LLCurl::getCurlThread()->update(1); + if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size()) + { + mHTTPTime = mTimer.getElapsedTimeF32() ; + mState = IDLE; + } + break; + case GL_TEX: + mState = IDLE; + break; + case REFETCH_VIS_CACHE: + if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) + { + mRefetchVisCacheTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; + mState = IDLE; + mFetcher->lockFetcher(true); + } + break; + case REFETCH_VIS_HTTP: + if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) + { + mRefetchVisHTTPTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime; + mState = IDLE; + mFetcher->lockFetcher(true); + } + break; + default: + mState = IDLE; + break; + } + + return mState == IDLE; +} + +void LLTextureFetchDebugger::callbackCacheRead(S32 id, bool success, LLImageFormatted* image, + S32 imagesize, BOOL islocal) +{ + if (success) + { + mFetchingHistory[id].mFormattedImage = image; + } + mTextureCache->readComplete(mFetchingHistory[id].mCacheHandle, false); + mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); +} + +void LLTextureFetchDebugger::callbackCacheWrite(S32 id, bool success) +{ + mTextureCache->writeComplete(mFetchingHistory[id].mCacheHandle); + mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); +} + +void LLTextureFetchDebugger::callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux) +{ + if (success) + { + llassert_always(raw); + mFetchingHistory[id].mRawImage = raw; + } +} + +void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer, + bool partial, bool success) +{ + mNbCurlRequests--; + if (success) + { + mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE; + mNbCurlCompleted++; + + S32 data_size = buffer->countAfter(channels.in(), NULL); + mFetchingHistory[id].mCurlReceivedSize += data_size; + //llinfos << "Fetch Debugger : got results for " << id << ", data_size = " << data_size << ", received = " << mFetchingHistory[id].mCurlReceivedSize << ", requested = " << mFetchingHistory[id].mRequestedSize << ", partial = " << partial << llendl; + if ((mFetchingHistory[id].mCurlReceivedSize >= mFetchingHistory[id].mRequestedSize) || !partial || (mFetchingHistory[id].mRequestedSize == 600)) + { + U8* d_buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size); + buffer->readAfter(channels.in(), NULL, d_buffer, data_size); + + llassert_always(mFetchingHistory[id].mFormattedImage.isNull()); + { + // For now, create formatted image based on extension + std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[id].mID.asString().c_str(); + std::string extension = gDirUtilp->getExtension(texture_url); + mFetchingHistory[id].mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension)); + if (mFetchingHistory[id].mFormattedImage.isNull()) + { + mFetchingHistory[id].mFormattedImage = new LLImageJ2C; // default + } + } + + mFetchingHistory[id].mFormattedImage->setData(d_buffer, data_size); + } + } + else //failed + { + mFetchingHistory[id].mHTTPFailCount++; + if(mFetchingHistory[id].mHTTPFailCount < 5) + { + // Fetch will have to be redone + mFetchingHistory[id].mCurlState = FetchEntry::CURL_NOT_DONE; + } + else //skip + { + mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE; + mNbCurlCompleted++; + } + } +} + + +//--------------------- +/////////////////////////////////////////////////////////////////////////////////////////// +//End LLTextureFetchDebugger +/////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 35df7d816f..107e1623b0 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -34,14 +34,17 @@ #include "llcurl.h" #include "lltextureinfo.h" #include "llapr.h" +#include "llimageworker.h" +//#include "lltexturecache.h" class LLViewerTexture; class LLTextureFetchWorker; class HTTPGetResponder; -class LLTextureCache; class LLImageDecodeThread; class LLHost; class LLViewerAssetStats; +class LLTextureFetchDebugger; +class LLTextureCache; // Interface class class LLTextureFetch : public LLWorkerThread @@ -164,6 +167,9 @@ private: LLMutex mQueueMutex; //to protect mRequestMap and mCommands only LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. + static LLStat sCacheHitRate; + static LLStat sCacheReadLatency; + LLTextureCache* mTextureCache; LLImageDecodeThread* mImageDecodeThread; LLCurlRequest* mCurlGetRequest; @@ -209,7 +215,195 @@ public: // attempt to log metrics follows a break in the metrics stream // reporting due to either startup or a problem POSTing data. static volatile bool svMetricsDataBreak; + +private: + //debug use + LLTextureFetchDebugger* mFetchDebugger; + bool mFetcherLocked; + +public: + //debug use + LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;} + void lockFetcher(bool lock) { mFetcherLocked = lock;} }; +//debug use +class LLTextureFetchDebugger +{ + friend class LLTextureFetch; +public: + LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) ; + ~LLTextureFetchDebugger(); + +public: + enum e_debug_state + { + IDLE = 0, + READ_CACHE, + WRITE_CACHE, + DECODING, + HTTP_FETCHING, + GL_TEX, + REFETCH_VIS_CACHE, + REFETCH_VIS_HTTP, + REFETCH_ALL_CACHE, + REFETCH_ALL_HTTP, + INVALID + }; + +private: + struct FetchEntry + { + enum e_curl_state + { + CURL_NOT_DONE = 0, + CURL_IN_PROGRESS, + CURL_DONE + }; + LLUUID mID; + S32 mRequestedSize; + S32 mDecodedLevel; + S32 mFetchedSize; + S32 mDecodedSize; + BOOL mNeedsAux; + U32 mCacheHandle; + LLPointer<LLImageFormatted> mFormattedImage; + LLPointer<LLImageRaw> mRawImage; + e_curl_state mCurlState; + S32 mCurlReceivedSize; + S32 mHTTPFailCount; + + FetchEntry() : + mDecodedLevel(-1), + mFetchedSize(0), + mDecodedSize(0) + {} + FetchEntry(LLUUID& id, S32 r_size, /*S32 f_discard, S32 c,*/ S32 level, S32 f_size, S32 d_size) : + mID(id), + mRequestedSize(r_size), + mDecodedLevel(level), + mFetchedSize(f_size), + mDecodedSize(d_size), + mNeedsAux(false), + mHTTPFailCount(0) + {} + }; + std::vector<FetchEntry> mFetchingHistory; + + e_debug_state mState; + + F32 mCacheReadTime; + F32 mCacheWriteTime; + F32 mDecodingTime; + F32 mHTTPTime; + F32 mGLCreationTime; + + F32 mTotalFetchingTime; + F32 mRefetchVisCacheTime; + F32 mRefetchVisHTTPTime; + + LLTimer mTimer; + + LLTextureFetch* mFetcher; + LLTextureCache* mTextureCache; + LLImageDecodeThread* mImageDecodeThread; + LLCurlRequest* mCurlGetRequest; + + S32 mNumFetchedTextures; + S32 mNumCacheHits; + S32 mNumVisibleFetchedTextures; + S32 mNumVisibleFetchingRequests; + U32 mFetchedData; + U32 mDecodedData; + U32 mVisibleFetchedData; + U32 mVisibleDecodedData; + U32 mRenderedData; + U32 mRenderedDecodedData; + U32 mFetchedPixels; + U32 mRenderedPixels; + U32 mRefetchedData; + U32 mRefetchedPixels; + + BOOL mFreezeHistory; + + std::string mHTTPUrl; + S32 mNbCurlRequests; + S32 mNbCurlCompleted; + +public: + bool update(); //called in the main thread once per frame + + //fetching history + void clearHistory(); + void addHistoryEntry(LLTextureFetchWorker* worker); + + void setCurlGetRequest(LLCurlRequest* request) { mCurlGetRequest = request;} + + void startDebug(); + void stopDebug(); //stop everything + void debugCacheRead(); + void debugCacheWrite(); + void debugHTTP(); + void debugDecoder(); + void debugGLTextureCreation(); + void debugRefetchVisibleFromCache(); + void debugRefetchVisibleFromHTTP(); + + void callbackCacheRead(S32 id, bool success, LLImageFormatted* image, + S32 imagesize, BOOL islocal); + void callbackCacheWrite(S32 id, bool success); + void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux); + void callbackHTTP(S32 id, const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer, + bool partial, bool success); + + + e_debug_state getState() {return mState;} + S32 getNumFetchedTextures() {return mNumFetchedTextures;} + S32 getNumFetchingRequests() {return mFetchingHistory.size();} + S32 getNumCacheHits() {return mNumCacheHits;} + S32 getNumVisibleFetchedTextures() {return mNumVisibleFetchedTextures;} + S32 getNumVisibleFetchingRequests() {return mNumVisibleFetchingRequests;} + U32 getFetchedData() {return mFetchedData;} + U32 getDecodedData() {return mDecodedData;} + U32 getVisibleFetchedData() {return mVisibleFetchedData;} + U32 getVisibleDecodedData() {return mVisibleDecodedData;} + U32 getRenderedData() {return mRenderedData;} + U32 getRenderedDecodedData() {return mRenderedDecodedData;} + U32 getFetchedPixels() {return mFetchedPixels;} + U32 getRenderedPixels() {return mRenderedPixels;} + U32 getRefetchedData() {return mRefetchedData;} + U32 getRefetchedPixels() {return mRefetchedPixels;} + + F32 getCacheReadTime() {return mCacheReadTime;} + F32 getCacheWriteTime() {return mCacheWriteTime;} + F32 getDecodeTime() {return mDecodingTime;} + F32 getGLCreationTime() {return mGLCreationTime;} + F32 getHTTPTime() {return mHTTPTime;} + F32 getTotalFetchingTime() {return mTotalFetchingTime;} + F32 getRefetchVisCacheTime() {return mRefetchVisCacheTime;} + F32 getRefetchVisHTTPTime() {return mRefetchVisHTTPTime;} + +private: + void init(); + void clearTextures();//clear fetching results of all textures. + void clearCache(); + + void lockFetcher(); + void unlockFetcher(); + + void lockCache(); + void unlockCache(); + + void lockDecoder(); + void unlockDecoder(); + + S32 fillCurlQueue(); + +private: + static bool sDebuggerEnabled; +public: + static bool isEnabled() {return sDebuggerEnabled;} +}; #endif // LL_LLTEXTUREFETCH_H diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 1c89766b26..425bf7ee87 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -57,8 +57,6 @@ extern F32 texmem_lower_bound_scale; LLTextureView *gTextureView = NULL; -LLTextureSizeView *gTextureSizeView = NULL; -LLTextureSizeView *gTextureCategoryView = NULL; #define HIGH_PRIORITY 100000000.f @@ -386,7 +384,7 @@ public: Params() : texture_view("texture_view") { - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); changeDefault(rect, LLRect(0,0,100,line_height * 4)); } }; @@ -411,7 +409,7 @@ void LLAvatarTexBar::draw() LLVOAvatarSelf* avatarp = gAgentAvatarp; if (!avatarp) return; - const S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + const S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); const S32 v_offset = 0; const S32 l_offset = 3; @@ -485,7 +483,7 @@ public: Params() : texture_view("texture_view") { - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); changeDefault(rect, LLRect(0,0,100,line_height * 4)); } }; @@ -513,7 +511,7 @@ void LLGLTexMemBar::draw() F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ; F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - S32 v_offset = (S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); + S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024); F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ; @@ -527,80 +525,24 @@ void LLGLTexMemBar::draw() LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6, text_color, LLFontGL::LEFT, LLFontGL::TOP); - text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d", + text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB", total_mem, max_total_mem, bound_mem, max_bound_mem, LLRenderTarget::sBytesAllocated/(1024*1024), LLImageRaw::sGlobalRawMemory >> 20, discard_bias, - cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests); - //, cache_entries, cache_max_entries - - LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3, + cache_usage, cache_max_usage); + LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*4, text_color, LLFontGL::LEFT, LLFontGL::TOP); - //---------------------------------------------------------------------------- -#if 0 - S32 bar_left = 400; - S32 bar_width = 200; - S32 top = line_height*3 - 2 + v_offset; - S32 bottom = top - 6; - S32 left = bar_left; - S32 right = left + bar_width; - F32 bar_scale; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // GL Mem Bar - - left = bar_left; - text = "GL"; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3, + text = llformat("Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d", + total_texture_downloaded, total_object_downloaded, total_http_requests); + //, cache_entries, cache_max_entries + LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3, text_color, LLFontGL::LEFT, LLFontGL::TOP); - - left = bar_left+20; - right = left + bar_width; - - gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); // grey - gl_rect_2d(left, top, right, bottom); - - bar_scale = (F32)bar_width / (max_total_mem * 1.5f); - right = left + llfloor(total_mem * bar_scale); - right = llclamp(right, bar_left, bar_left + bar_width); - - color = (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) ? LLColor4::green : - (total_mem < max_total_mem) ? LLColor4::yellow : LLColor4::red; - color[VALPHA] = .75f; - gGL.diffuseColor4fv(color.mV); - - gl_rect_2d(left, top, right, bottom); // red/yellow/green - - // - bar_left += bar_width + bar_space; - //top = bottom - 2; bottom = top - 6; - - // Bound Mem Bar - - left = bar_left; - text = "GL"; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - left = bar_left + 20; - right = left + bar_width; - - gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); - gl_rect_2d(left, top, right, bottom); - - color = (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) ? LLColor4::green : - (bound_mem < max_bound_mem) ? LLColor4::yellow : LLColor4::red; - color[VALPHA] = .75f; - gGL.diffuseColor4fv(color.mV); - gl_rect_2d(left, top, right, bottom); -#else S32 left = 0 ; -#endif //---------------------------------------------------------------------------- text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d", @@ -669,8 +611,7 @@ BOOL LLGLTexMemBar::handleMouseDown(S32 x, S32 y, MASK mask) LLRect LLGLTexMemBar::getRequiredRect() { LLRect rect; - //rect.mTop = 50; - rect.mTop = 0; + rect.mTop = 50; //LLFontGL::getFontMonospace()->getLineHeight() * 6; return rect; } @@ -954,9 +895,11 @@ void LLTextureView::draw() LLRect tmbr; tmbp.name("gl texmem bar"); tmbp.rect(tmbr); + tmbp.follows.flags = FOLLOWS_LEFT|FOLLOWS_TOP; tmbp.texture_view(this); mGLTexMemBar = LLUICtrlFactory::create<LLGLTexMemBar>(tmbp); - addChildInBack(mGLTexMemBar); + addChild(mGLTexMemBar); + sendChildToFront(mGLTexMemBar); LLAvatarTexBar::Params atbp; LLRect atbr; @@ -965,16 +908,13 @@ void LLTextureView::draw() atbp.rect(atbr); mAvatarTexBar = LLUICtrlFactory::create<LLAvatarTexBar>(atbp); addChild(mAvatarTexBar); + sendChildToFront(mAvatarTexBar); reshape(getRect().getWidth(), getRect().getHeight(), TRUE); - /* - count = gTextureList.getNumImages(); - std::string info_string; - info_string = llformat("Global Info:\nTexture Count: %d", count); - mInfoTextp->setText(info_string); - */ - + LLUI::popMatrix(); + LLUI::pushMatrix(); + LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); for (child_list_const_iter_t child_iter = getChildList()->begin(); child_iter != getChildList()->end(); ++child_iter) @@ -1049,302 +989,4 @@ BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent) return FALSE; } -//----------------------------------------------------------------- -LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) : LLContainerView(p) -{ - setVisible(FALSE) ; - - mTextureSizeBarWidth = 30 ; -} - -LLTextureSizeView::~LLTextureSizeView() -{ - if(mTextureSizeBar.size()) - { - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - delete mTextureSizeBar[i] ; - } - mTextureSizeBar.clear() ; - } -} -void LLTextureSizeView::draw() -{ - if(mType == TEXTURE_MEM_OVER_SIZE) - { - drawTextureSizeGraph(); - } - else - { - drawTextureCategoryGraph() ; - } - - LLView::draw(); -} - -BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) -{ - if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight) - { - mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ; - } - - return TRUE ; -} - -//draw real-time texture mem bar over size -void LLTextureSizeView::drawTextureSizeGraph() -{ - if(mTextureSizeBar.size() == 0) - { - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ; - mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; - - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , - line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ; - } - } - - F32 size_bar_scale = drawTextureSizeDistributionGraph() ; - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - mTextureSizeBar[i]->setTop(LLImageGL::sTextureLoadedCounter[i], LLImageGL::sTextureBoundCounter[i], size_bar_scale) ; - mTextureSizeBar[i]->draw() ; - } - LLImageGL::resetCurTexSizebar(); -} - -//draw background of texture size bar graph -F32 LLTextureSizeView::drawTextureSizeDistributionGraph() -{ - //scale - F32 scale = 1.0f ; - - LLGLSUIDefault gls_ui; - - { - S32 count = 0 ; - for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++) - { - if(LLImageGL::sTextureLoadedCounter[i] > count) - { - count = LLImageGL::sTextureLoadedCounter[i] ; - } - } - if(count > mTextureSizeBarRect.getHeight()) - { - scale = (F32)mTextureSizeBarRect.getHeight() / count ; - } - } - - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - S32 left = mTextureSizeBarRect.mLeft ; - S32 bottom = mTextureSizeBarRect.mBottom ; - S32 right = mTextureSizeBarRect.mRight ; - S32 top = mTextureSizeBarRect.mTop ; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - //background rect - gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ; - - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f); - gl_line_2d(left, bottom, right, bottom) ; //x axis - gl_line_2d(left, bottom, left, top) ; //y axis - - //ruler - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f); - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - gl_line_2d(left, i, right, i) ; - } - - //texts - //-------------------------------------------------- - F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; - std::string text; - - //------- - //x axis: size label - text = llformat("%d", 0) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++) - { - text = llformat("%d", (1 << (i / 2)) + ((i & 1) ? ((1 << (i / 2)) >> 1) : 0)) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - text = llformat("(w + h)/2") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 10, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - //------- - - //y axis: number label - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - text = llformat("%d", (S32)((i - bottom) / scale)) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - - //-------------------------------------------------- - F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ; - text = llformat("Loaded") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2, - loaded_color, LLFontGL::LEFT, LLFontGL::TOP); - - F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ; - text = llformat("Bound") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2, - bound_color, LLFontGL::LEFT, LLFontGL::TOP); - - //-------------------------------------------------- - - //title - text = llformat("Texture Size Distribution") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - return scale ; -} - -//draw real-time texture mem bar over category -void LLTextureSizeView::drawTextureCategoryGraph() -{ - if(mTextureSizeBar.size() == 0) - { - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ; - mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; - - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , - line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ; - } - } - - F32 size_bar_scale = drawTextureCategoryDistributionGraph() ; - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - U32 k = LLViewerTexture::getIndexFromCategory(i) ; - mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ; - mTextureSizeBar[i]->draw() ; - } - LLImageGL::resetCurTexSizebar(); -} - -//draw background for TEXTURE_MEM_OVER_CATEGORY -F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() -{ - //scale - F32 scale = 4.0f ; - - LLGLSUIDefault gls_ui; - - { - S32 count = 0 ; - for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++) - { - S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ; - if(tmp > count) - { - count = tmp ; - } - } - if(count > mTextureSizeBarRect.getHeight() * 0.25f) - { - scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ; - } - } - - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - S32 left = mTextureSizeBarRect.mLeft ; - S32 bottom = mTextureSizeBarRect.mBottom ; - S32 right = mTextureSizeBarRect.mRight ; - S32 top = mTextureSizeBarRect.mTop ; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - //background rect - gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ; - - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f); - gl_line_2d(left, bottom, right, bottom) ; //x axis - gl_line_2d(left, bottom, left, top) ; //y axis - - //ruler - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f); - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - gl_line_2d(left, i, right, i) ; - } - - //texts - //-------------------------------------------------- - F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; - std::string text; - - //------- - //x axis: size label - static char category[LLViewerTexture::MAX_GL_IMAGE_CATEGORY][4] = - {"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Loc", "Scr", "Dyn", "Mdi", "ALT", "Oth" } ; - - text = llformat("%s", category[0]) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++) - { - text = llformat("%s", category[i]) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - //------- - - //y axis: number label - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - text = llformat("%d", (S32)((i - bottom) / scale)) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - text = llformat("MB") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - //-------------------------------------------------- - F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ; - text = llformat("Loaded") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2, - loaded_color, - LLFontGL::LEFT, LLFontGL::TOP); - - F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ; - text = llformat("Bound") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2, - bound_color, LLFontGL::LEFT, LLFontGL::TOP); - - //-------------------------------------------------- - - //title - text = llformat("Texture Category Distribution") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - - return scale ; -} diff --git a/indra/newview/lltextureview.h b/indra/newview/lltextureview.h index 3723eb737b..900b4e17d8 100644 --- a/indra/newview/lltextureview.h +++ b/indra/newview/lltextureview.h @@ -75,41 +75,6 @@ public: }; class LLGLTexSizeBar; -class LLTextureSizeView : public LLContainerView -{ -protected: - LLTextureSizeView(const Params&); - friend class LLUICtrlFactory; -public: - ~LLTextureSizeView(); - - /*virtual*/ void draw(); - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) ; - - void setType(S32 type) {mType = type ;} - enum - { - TEXTURE_MEM_OVER_SIZE, - TEXTURE_MEM_OVER_CATEGORY - }; -private: - //draw background for TEXTURE_MEM_OVER_SIZE - F32 drawTextureSizeDistributionGraph() ; - //draw real-time texture mem bar over size - void drawTextureSizeGraph(); - - //draw background for TEXTURE_MEM_OVER_CATEGORY - F32 drawTextureCategoryDistributionGraph() ; - //draw real-time texture mem bar over category - void drawTextureCategoryGraph(); -private: - std::vector<LLGLTexSizeBar*> mTextureSizeBar ; - LLRect mTextureSizeBarRect ; - S32 mTextureSizeBarWidth ; - S32 mType ; -}; extern LLTextureView *gTextureView; -extern LLTextureSizeView *gTextureSizeView; -extern LLTextureSizeView *gTextureCategoryView; #endif // LL_TEXTURE_VIEW_H diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index da691a2d0c..0eec7f0afd 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -180,11 +180,14 @@ LLToast::~LLToast() //-------------------------------------------------------------------------- void LLToast::hide() { - setVisible(FALSE); - setFading(false); - mTimer->stop(); - mIsHidden = true; - mOnFadeSignal(this); + if (!mIsHidden) + { + setVisible(FALSE); + setFading(false); + mTimer->stop(); + mIsHidden = true; + mOnFadeSignal(this); + } } void LLToast::onFocusLost() @@ -215,6 +218,13 @@ void LLToast::setFadingTime(S32 seconds) mToastFadingTime = seconds; } +void LLToast::closeToast() +{ + mOnDeleteToastSignal(this); + + closeFloater(); +} + S32 LLToast::getTopPad() { if(mWrapperPanel) @@ -296,9 +306,7 @@ void LLToast::reshapeToPanel() if(!panel) return; - LLRect panel_rect = panel->getRect(); - - panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight()); + LLRect panel_rect = panel->getLocalRect(); panel->setShape(panel_rect); LLRect toast_rect = getRect(); diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 0b06728935..e1d99b1bcb 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -75,6 +75,7 @@ class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast> public: typedef boost::function<void (LLToast* toast)> toast_callback_t; typedef boost::signals2::signal<void (LLToast* toast)> toast_signal_t; + typedef boost::signals2::signal<void (LLToast* toast, bool mouse_enter)> toast_hover_check_signal_t; struct Params : public LLInitParam::Block<Params> { @@ -131,7 +132,7 @@ public: void reshapeToPanel(); // get toast's panel - LLPanel* getPanel() { return mPanel; } + LLPanel* getPanel() const { return mPanel; } // enable/disable Toast's Hide button void setHideButtonEnabled(bool enabled); // @@ -155,6 +156,8 @@ public: void setFadingTime(S32 seconds); + void closeToast(); + /** * Returns padding between floater top and wrapper_panel top. * This padding should be taken into account when positioning or reshaping toasts @@ -167,9 +170,9 @@ public: // get information whether the notification corresponding to the toast is valid or not bool isNotificationValid(); // get toast's Notification ID - const LLUUID getNotificationID() { return mNotificationID;} + const LLUUID getNotificationID() const { return mNotificationID;} // get toast's Session ID - const LLUUID getSessionID() { return mSessionID;} + const LLUUID getSessionID() const { return mSessionID;} // void setCanFade(bool can_fade); // @@ -179,19 +182,12 @@ public: // set whether this toast considered as hidden or not void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; } - const LLNotificationPtr& getNotification() { return mNotification;} + const LLNotificationPtr& getNotification() const { return mNotification;} // Registers signals/callbacks for events - toast_signal_t mOnFadeSignal; - toast_signal_t mOnDeleteToastSignal; - toast_signal_t mOnToastDestroyedSignal; - boost::signals2::connection setOnFadeCallback(toast_callback_t cb) { return mOnFadeSignal.connect(cb); } - boost::signals2::connection setOnToastDestroyedCallback(toast_callback_t cb) { return mOnToastDestroyedSignal.connect(cb); } - - typedef boost::function<void (LLToast* toast, bool mouse_enter)> toast_hover_check_callback_t; - typedef boost::signals2::signal<void (LLToast* toast, bool mouse_enter)> toast_hover_check_signal_t; - toast_hover_check_signal_t mOnToastHoverSignal; - boost::signals2::connection setOnToastHoverCallback(toast_hover_check_callback_t cb) { return mOnToastHoverSignal.connect(cb); } + boost::signals2::connection setOnFadeCallback(const toast_signal_t::slot_type& cb) { return mOnFadeSignal.connect(cb); } + boost::signals2::connection setOnToastDestroyedCallback(const toast_signal_t::slot_type& cb) { return mOnToastDestroyedSignal.connect(cb); } + boost::signals2::connection setOnToastHoverCallback(const toast_hover_check_signal_t::slot_type& cb) { return mOnToastHoverSignal.connect(cb); } boost::signals2::connection setMouseEnterCallback( const commit_signal_t::slot_type& cb ) { return mToastMouseEnterSignal.connect(cb); }; boost::signals2::connection setMouseLeaveCallback( const commit_signal_t::slot_type& cb ) { return mToastMouseLeaveSignal.connect(cb); }; @@ -237,6 +233,11 @@ private: bool mIsFading; bool mIsHovered; + toast_signal_t mOnFadeSignal; + toast_signal_t mOnDeleteToastSignal; + toast_signal_t mOnToastDestroyedSignal; + toast_hover_check_signal_t mOnToastHoverSignal; + commit_signal_t mToastMouseEnterSignal; commit_signal_t mToastMouseLeaveSignal; }; diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 0f337825e9..8fef2ed6d1 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -69,8 +69,22 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal mLabel(notification->getName()), mLineEditor(NULL) { + // EXP-1822 + // save currently focused view, so that return focus to it + // on destroying this toast. + LLView* current_selection = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus()); + while(current_selection) + { + if (current_selection->isFocusRoot()) + { + mPreviouslyFocusedView = current_selection->getHandle(); + break; + } + current_selection = current_selection->getParent(); + } + const LLFontGL* font = LLFontGL::getFontSansSerif(); - const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); + const S32 LINE_HEIGHT = font->getLineHeight(); const S32 EDITOR_HEIGHT = 20; LLNotificationFormPtr form = mNotification->getForm(); @@ -365,7 +379,7 @@ bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std:: } const LLFontGL* font = mCheck->getFont(); - const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); + const S32 LINE_HEIGHT = font->getLineHeight(); // Extend dialog for "check next time" S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD; @@ -408,6 +422,13 @@ LLToastAlertPanel::~LLToastAlertPanel() { LLTransientFloaterMgr::instance().removeControlView( LLTransientFloaterMgr::GLOBAL, this); + + // EXP-1822 + // return focus to the previously focused view if the viewer is not exiting + if (mPreviouslyFocusedView.get() && !LLApp::isExiting()) + { + mPreviouslyFocusedView.get()->setFocus(TRUE); + } } BOOL LLToastAlertPanel::hasTitleBar() const diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index 7b157f19bb..d1be5e018e 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -113,6 +113,7 @@ private: LLFrameTimer mDefaultBtnTimer; // For Dialogs that take a line as text as input: LLLineEditor* mLineEditor; + LLHandle<LLView> mPreviouslyFocusedView; }; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index de305bf3d9..a473ee7ce0 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -52,7 +52,7 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification, const LLRect& rect, bool show_images) : +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : LLToastPanel(notification), mTextBox(NULL), mInfoPanel(NULL), @@ -243,8 +243,8 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt mBtnCallbackData.push_back(userdata); LLButton::Params p; - bool is_ignore_btn = form_element["index"].asInteger() == -1; - const LLFontGL* font = is_ignore_btn ? sFontSmall: sFont; // for ignore button in script dialog + bool make_small_btn = form_element["index"].asInteger() == -1 || form_element["index"].asInteger() == -2; + const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog p.name(form_element["name"].asString()); p.label(form_element["text"].asString()); p.font(font); @@ -264,7 +264,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt p.rect.width = 1; p.auto_resize = true; } - else if (mIsScriptDialog && is_ignore_btn) + else if (mIsScriptDialog && make_small_btn) { // this is ignore button, make it smaller p.rect.height = BTN_HEIGHT_SMALL; @@ -536,7 +536,7 @@ void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id } } -void LLToastNotifyPanel::disableRespondedOptions(LLNotificationPtr& notification) +void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) { LLSD response = notification->getResponse(); for (LLSD::map_const_iterator response_it = response.beginMap(); diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 57711b3d80..db517ec858 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -60,7 +60,7 @@ public: * @deprecated if you intend to instantiate LLToastNotifyPanel - it's point to * implement right class for desired toast panel. @see LLGenericTipPanel as example. */ - LLToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); virtual ~LLToastNotifyPanel(); LLPanel * getControlPanel() { return mControlPanel; } @@ -118,7 +118,7 @@ protected: /** * Process response data. Will disable selected options */ - void disableRespondedOptions(LLNotificationPtr& notification); + void disableRespondedOptions(const LLNotificationPtr& notification); bool mIsTip; bool mAddedDefaultBtn; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index fc69157a40..c33fde99c5 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -29,7 +29,9 @@ #include "llpanelgenerictip.h" #include "llpanelonlinestatus.h" #include "llnotifications.h" +#include "lltoastnotifypanel.h" #include "lltoastpanel.h" +#include "lltoastscriptquestion.h" //static const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32) @@ -68,7 +70,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) if (message->getVisible()) { S32 heightDelta = 0; - S32 maxTextHeight = (S32)(message->getDefaultFont()->getLineHeight() * maxLineCount); + S32 maxTextHeight = message->getDefaultFont()->getLineHeight() * maxLineCount; LLRect messageRect = message->getRect(); S32 oldTextHeight = messageRect.getHeight(); @@ -106,6 +108,17 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification( res = new LLPanelGenericTip(notification); } } + else if("notify" == notification->getType()) + { + if (notification->getPriority() == NOTIFICATION_PRIORITY_CRITICAL) + { + res = new LLToastScriptQuestion(notification); + } + else + { + res = new LLToastNotifyPanel(notification); + } + } /* else if(...) create all other specific non-public toast panel diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp new file mode 100644 index 0000000000..feeb8ca77b --- /dev/null +++ b/indra/newview/lltoastscriptquestion.cpp @@ -0,0 +1,130 @@ +/** + * @file lltoastscriptquestion.cpp + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llbutton.h" +#include "llnotifications.h" +#include "lltoastscriptquestion.h" + +const int LEFT_PAD = 10; +const int BUTTON_HEIGHT = 27; +const int MAX_LINES_COUNT = 50; + +LLToastScriptQuestion::LLToastScriptQuestion(const LLNotificationPtr& notification) +: +LLToastPanel(notification) +{ + buildFromFile("panel_script_question_toast.xml"); +} + +BOOL LLToastScriptQuestion::postBuild() +{ + createButtons(); + + LLTextBox* mMessage = getChild<LLTextBox>("top_info_message"); + LLTextBox* mFooter = getChild<LLTextBox>("bottom_info_message"); + + mMessage->setValue(mNotification->getMessage()); + mFooter->setValue(mNotification->getFooter()); + + snapToMessageHeight(); + + return TRUE; +} +void LLToastScriptQuestion::snapToMessageHeight() +{ + LLTextBox* mMessage = getChild<LLTextBox>("top_info_message"); + LLTextBox* mFooter = getChild<LLTextBox>("bottom_info_message"); + if (!mMessage || !mFooter) + { + return; + } + + if (mMessage->getVisible() && mFooter->getVisible()) + { + S32 heightDelta = 0; + S32 maxTextHeight = (mMessage->getDefaultFont()->getLineHeight() * MAX_LINES_COUNT) + + (mFooter->getDefaultFont()->getLineHeight() * MAX_LINES_COUNT); + + LLRect messageRect = mMessage->getRect(); + LLRect footerRect = mFooter->getRect(); + + S32 oldTextHeight = messageRect.getHeight() + footerRect.getHeight(); + + S32 requiredTextHeight = mMessage->getTextBoundingRect().getHeight() + mFooter->getTextBoundingRect().getHeight(); + S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); + + heightDelta = newTextHeight - oldTextHeight - heightDelta; + + reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); + } +} + +void LLToastScriptQuestion::createButtons() +{ + LLNotificationFormPtr form = mNotification->getForm(); + int num_elements = form->getNumElements(); + int buttons_width = 0; + + for (int i = 0; i < num_elements; ++i) + { + LLSD form_element = form->getElement(i); + if ("button" == form_element["type"].asString()) + { + LLButton::Params p; + const LLFontGL* font = LLFontGL::getFontSansSerif(); + p.name(form_element["name"].asString()); + p.label(form_element["text"].asString()); + p.layout("topleft"); + p.font(font); + p.rect.height(BUTTON_HEIGHT); + p.click_callback.function(boost::bind(&LLToastScriptQuestion::onButtonClicked, this, form_element["name"].asString())); + p.rect.left = LEFT_PAD; + p.rect.width = font->getWidth(form_element["text"].asString()); + p.auto_resize = true; + p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); + p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); + + LLButton* button = LLUICtrlFactory::create<LLButton>(p); + button->autoResize(); + getChild<LLPanel>("buttons_panel")->addChild(button); + + LLRect rect = button->getRect(); + rect.setLeftTopAndSize(buttons_width, rect.mTop, rect.getWidth(), rect.getHeight()); + button->setRect(rect); + + buttons_width += rect.getWidth() + LEFT_PAD; + } + } +} + +void LLToastScriptQuestion::onButtonClicked(std::string btn_name) +{ + LLSD response = mNotification->getResponseTemplate(); + response[btn_name] = true; + mNotification->respond(response); +} diff --git a/indra/newview/lltoastscriptquestion.h b/indra/newview/lltoastscriptquestion.h new file mode 100644 index 0000000000..3a557f60f6 --- /dev/null +++ b/indra/newview/lltoastscriptquestion.h @@ -0,0 +1,49 @@ +/** + * @file lltoastscriptquestion.h + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltoastpanel.h" + +#ifndef LLTOASTSCRIPTQUESTION_H_ +#define LLTOASTSCRIPTQUESTION_H_ + +class LLToastScriptQuestion : public LLToastPanel +{ + LOG_CLASS(LLToastScriptQuestion); + +public: + LLToastScriptQuestion(const LLNotificationPtr& notification); + virtual BOOL postBuild(); + virtual ~LLToastScriptQuestion(){}; + +private: + void snapToMessageHeight(); + + void createButtons(); + void onButtonClicked(std::string btn_name); +}; + +#endif /* LLTOASTSCRIPTQUESTION_H_ */ diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index eccb2cf2f1..81ad96f39e 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -75,6 +75,7 @@ LLToolBarView::LLToolBarView(const LLToolBarView::Params& p) mDragStarted(false), mShowToolbars(true), mDragToolbarButton(NULL), + mDragItem(NULL), mToolbarsLoaded(false) { for (S32 i = 0; i < TOOLBAR_COUNT; i++) @@ -579,7 +580,6 @@ BOOL LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetTyp uuid_vec_t cargo_ids; types.push_back(DAD_WIDGET); cargo_ids.push_back(uuid); - gClipboard.setSourceObject(uuid,LLAssetType::AT_WIDGET); LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_VIEWER; LLUUID srcID; LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src, srcID); @@ -662,6 +662,18 @@ void LLToolBarView::resetDragTool(LLToolBarButton* toolbarButton) gToolBarView->mDragToolbarButton = toolbarButton; } +// Provide a handle on a free standing inventory item containing references to the tool. +// This might be used by Drag and Drop to move around references to tool items. +LLInventoryObject* LLToolBarView::getDragItem() +{ + if (mDragToolbarButton) + { + LLUUID item_uuid = mDragToolbarButton->getCommandId().uuid(); + mDragItem = new LLInventoryObject (item_uuid, LLUUID::null, LLAssetType::AT_WIDGET, ""); + } + return mDragItem; +} + void LLToolBarView::setToolBarsVisible(bool visible) { mShowToolbars = visible; diff --git a/indra/newview/lltoolbarview.h b/indra/newview/lltoolbarview.h index be66bcae36..9c4194ebed 100644 --- a/indra/newview/lltoolbarview.h +++ b/indra/newview/lltoolbarview.h @@ -31,6 +31,7 @@ #include "lluictrl.h" #include "lltoolbar.h" #include "llcommandmanager.h" +#include "llinventory.h" class LLUICtrlFactory; @@ -106,6 +107,7 @@ public: static BOOL handleDragTool(S32 x, S32 y, const LLUUID& uuid, LLAssetType::EType type); static BOOL handleDropTool(void* cargo_data, S32 x, S32 y, LLToolBar* toolbar); static void resetDragTool(LLToolBarButton* toolbarButton); + LLInventoryObject* getDragItem(); bool isModified() const; @@ -129,6 +131,7 @@ private: bool mDragStarted; LLToolBarButton* mDragToolbarButton; + LLInventoryObject* mDragItem; bool mShowToolbars; }; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 8c32dfcb4d..4f4eef0f3d 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -48,6 +48,7 @@ #include "llpreviewnotecard.h" #include "llrootview.h" #include "llselectmgr.h" +#include "lltoolbarview.h" #include "lltoolmgr.h" #include "lltooltip.h" #include "lltrans.h" @@ -333,14 +334,15 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary() }; LLToolDragAndDrop::LLToolDragAndDrop() -: LLTool(std::string("draganddrop"), NULL), - mDragStartX(0), - mDragStartY(0), - mSource(SOURCE_AGENT), - mCursor(UI_CURSOR_NO), - mLastAccept(ACCEPT_NO), - mDrop(FALSE), - mCurItemIndex(0) +: LLTool(std::string("draganddrop"), NULL), + mCargoCount(0), + mDragStartX(0), + mDragStartY(0), + mSource(SOURCE_AGENT), + mCursor(UI_CURSOR_NO), + mLastAccept(ACCEPT_NO), + mDrop(FALSE), + mCurItemIndex(0) { } @@ -2527,7 +2529,7 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory( } else if(mSource == SOURCE_VIEWER) { - item = (LLViewerInventoryItem*)gClipboard.getSourceObject(); + item = (LLViewerInventoryItem*)gToolBarView->getDragItem(); } if(item) return item; if(cat) return cat; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 188d36cd1b..245c2a23e6 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -86,8 +86,11 @@ public: EAcceptance getLastAccept() { return mLastAccept; } boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); } - - uuid_vec_t::size_type getCargoIDsCount() const { return mCargoIDs.size(); } + + void setCargoCount(U32 count) { mCargoCount = count; } + void resetCargoCount() { mCargoCount = 0; } + U32 getCargoCount() const { return (mCargoCount > 0) ? mCargoCount : mCargoIDs.size(); } + static S32 getOperationId() { return sOperationId; } protected: @@ -118,6 +121,8 @@ protected: protected: + U32 mCargoCount; + S32 mDragStartX; S32 mDragStartY; diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index 6bc7c6de11..ac01316462 100644 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -81,7 +81,7 @@ LLToolMgr::LLToolMgr() // Not a panel, register these callbacks globally. LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this)); LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this)); - LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this)); + LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this, _2)); gToolNull = new LLTool(LLStringUtil::null); // Does nothing setCurrentTool(gToolNull); @@ -245,8 +245,15 @@ bool LLToolMgr::canEdit() return LLViewerParcelMgr::getInstance()->allowAgentBuild(); } -void LLToolMgr::toggleBuildMode() +void LLToolMgr::toggleBuildMode(const LLSD& sdname) { + const std::string& param = sdname.asString(); + + if (param == "build" && !canEdit()) + { + return; + } + LLFloaterReg::toggleInstanceOrBringToFront("build"); bool build_visible = LLFloaterReg::instanceVisible("build"); diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h index d489c4c829..12649cfba2 100644 --- a/indra/newview/lltoolmgr.h +++ b/indra/newview/lltoolmgr.h @@ -54,7 +54,7 @@ public: bool inEdit(); bool canEdit(); - void toggleBuildMode(); + void toggleBuildMode(const LLSD& sdname); /* Determines if we are in Build mode or not. */ bool inBuildMode(); diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index c1cc9c7bc4..f3d8de1904 100755 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -162,10 +162,10 @@ void LLBingTranslationHandler::getTranslateURL( const std::string &text) const { url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=") - + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + to_lang; + + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + getAPILanguageCode(to_lang); if (!from_lang.empty()) { - url += "&from=" + from_lang; + url += "&from=" + getAPILanguageCode(from_lang); } } @@ -236,6 +236,12 @@ std::string LLBingTranslationHandler::getAPIKey() return gSavedSettings.getString("BingTranslateAPIKey"); } +// static +std::string LLBingTranslationHandler::getAPILanguageCode(const std::string& lang) +{ + return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese +} + LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang) : mFromLang(from_lang) , mToLang(to_lang) diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 424bc14587..c58e1adb8c 100755 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -157,6 +157,7 @@ public: /*virtual*/ bool isConfigured() const; private: static std::string getAPIKey(); + static std::string getAPILanguageCode(const std::string& lang); }; /** diff --git a/indra/newview/lluploaddialog.cpp b/indra/newview/lluploaddialog.cpp index df7c5be0d6..e59064c074 100644 --- a/indra/newview/lluploaddialog.cpp +++ b/indra/newview/lluploaddialog.cpp @@ -115,7 +115,7 @@ void LLUploadDialog::setMessage( const std::string& msg) token = strtok( NULL, "\n" ); } - S32 line_height = S32( font->getLineHeight() + 0.99f ); + S32 line_height = font->getLineHeight(); S32 dialog_width = max_msg_width + 2 * HPAD; S32 dialog_height = line_height * msg_lines.size() + 2 * VPAD; diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp index 56b5bbf942..cad5769042 100644 --- a/indra/newview/llurllineeditorctrl.cpp +++ b/indra/newview/llurllineeditorctrl.cpp @@ -89,5 +89,5 @@ void LLURLLineEditor::copyEscapedURLToClipboard() else // human-readable location text_to_copy = utf8str_to_wstring(unescaped_text); - gClipboard.copyFromString( text_to_copy ); + LLClipboard::instance().copyToClipboard(text_to_copy, 0, text_to_copy.size()); } diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index e621cf647e..4c59fd0371 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -30,6 +30,7 @@ #include "llregionhandle.h" #include "stdtypes.h" +#include "llvoavatar.h" /* * Classes and utility functions for per-thread and per-region @@ -126,6 +127,8 @@ LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionSta mFPS.merge(src.mFPS); } + // Avatar stats - data all comes from main thread, so leave alone. + // Requests for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i) { @@ -133,6 +136,7 @@ LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionSta mRequests[i].mDequeued.merge(src.mRequests[i].mDequeued); mRequests[i].mResponse.merge(src.mRequests[i].mResponse); } + } @@ -156,7 +160,9 @@ LLViewerAssetStats::LLViewerAssetStats() LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src) : mRegionHandle(src.mRegionHandle), - mResetTimestamp(src.mResetTimestamp) + mResetTimestamp(src.mResetTimestamp), + mPhaseStats(src.mPhaseStats), + mAvatarRezStates(src.mAvatarRezStates) { const PerRegionContainer::const_iterator it_end(src.mRegionStats.end()); for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it) @@ -252,6 +258,17 @@ LLViewerAssetStats::recordFPS(F32 fps) mCurRegionStats->mFPS.record(fps); } +void +LLViewerAssetStats::recordAvatarStats() +{ + std::vector<S32> rez_counts; + LLVOAvatar::getNearbyRezzedStats(rez_counts); + mAvatarRezStates = rez_counts; + mPhaseStats.clear(); + mPhaseStats["cloud"] = LLViewerStats::PhaseMap::getPhaseStats("cloud"); + mPhaseStats["cloud-or-gray"] = LLViewerStats::PhaseMap::getPhaseStats("cloud-or-gray"); +} + LLSD LLViewerAssetStats::asLLSD(bool compact_output) { @@ -282,6 +299,11 @@ LLViewerAssetStats::asLLSD(bool compact_output) static const LLSD::String max_tag("max"); static const LLSD::String mean_tag("mean"); + // Avatar sub-tags + static const LLSD::String avatar_tag("avatar"); + static const LLSD::String avatar_nearby_tag("nearby"); + static const LLSD::String avatar_phase_stats_tag("phase_stats"); + const duration_t now = LLViewerAssetStatsFF::get_timestamp(); mCurRegionStats->accumulateTime(now); @@ -329,7 +351,6 @@ LLViewerAssetStats::asLLSD(bool compact_output) slot[max_tag] = LLSD(F64(stats.mFPS.getMax())); slot[mean_tag] = LLSD(F64(stats.mFPS.getMean())); } - U32 grid_x(0), grid_y(0); grid_from_region_handle(it->first, &grid_x, &grid_y); reg_stat["grid_x"] = LLSD::Integer(grid_x); @@ -341,6 +362,16 @@ LLViewerAssetStats::asLLSD(bool compact_output) LLSD ret = LLSD::emptyMap(); ret["regions"] = regions; ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6); + LLSD avatar_info; + avatar_info[avatar_nearby_tag] = LLSD::emptyArray(); + for (S32 rez_stat=0; rez_stat < mAvatarRezStates.size(); ++rez_stat) + { + std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat); + avatar_info[avatar_nearby_tag][rez_status_name] = mAvatarRezStates[rez_stat]; + } + avatar_info[avatar_phase_stats_tag]["cloud"] = mPhaseStats["cloud"].getData(); + avatar_info[avatar_phase_stats_tag]["cloud-or-gray"] = mPhaseStats["cloud-or-gray"].getData(); + ret[avatar_tag] = avatar_info; return ret; } @@ -439,6 +470,14 @@ record_fps_main(F32 fps) gViewerAssetStatsMain->recordFPS(fps); } +void +record_avatar_stats() +{ + if (! gViewerAssetStatsMain) + return; + + gViewerAssetStatsMain->recordAvatarStats(); +} // 'thread1' - should be for TextureFetch thread diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index 73ec5974b2..8319752230 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -36,6 +36,7 @@ #include "llviewerassetstorage.h" #include "llsimplestat.h" #include "llsd.h" +#include "llvoavatar.h" /** * @class LLViewerAssetStats @@ -181,6 +182,9 @@ public: // Frames-Per-Second Samples void recordFPS(F32 fps); + // Avatar-related statistics + void recordAvatarStats(); + // Merge a source instance into a destination instance. This is // conceptually an 'operator+=()' method: // - counts are added @@ -252,6 +256,10 @@ protected: // Time of last reset duration_t mResetTimestamp; + + // Nearby avatar stats + std::vector<S32> mAvatarRezStates; + LLViewerStats::phase_stats_t mPhaseStats; }; @@ -310,6 +318,7 @@ void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_t void record_fps_main(F32 fps); +void record_avatar_stats(); /** * Region context, event and duration loggers for Thread 1. diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index cc3395115b..184033de42 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -32,8 +32,8 @@ #include "llstat.h" #include "lltimer.h" #include "m4math.h" +#include "llcoord.h" -class LLCoordGL; class LLViewerObject; // This rotation matrix moves the default OpenGL reference frame diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 093b84413a..f2712e7590 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -87,7 +87,6 @@ std::string gLastRunVersion; extern BOOL gResizeScreenTexture; extern BOOL gDebugGL; -extern BOOL gAuditTexture; //////////////////////////////////////////////////////////////////////////// // Listeners @@ -181,6 +180,16 @@ static bool handleReleaseGLBufferChanged(const LLSD& newvalue) return true; } +static bool handleLUTBufferChanged(const LLSD& newvalue) +{ + if (gPipeline.isInit()) + { + gPipeline.releaseLUTBuffers(); + gPipeline.createLUTBuffers(); + } + return true; +} + static bool handleAnisotropicChanged(const LLSD& newvalue) { LLImageGL::sGlobalUseAnisotropic = newvalue.asBoolean(); @@ -401,12 +410,6 @@ static bool handleRenderUseImpostorsChanged(const LLSD& newvalue) return true; } -static bool handleAuditTextureChanged(const LLSD& newvalue) -{ - gAuditTexture = newvalue.asBoolean(); - return true; -} - static bool handleRenderDebugGLChanged(const LLSD& newvalue) { gDebugGL = newvalue.asBoolean() || gDebugSession; @@ -569,9 +572,9 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); - gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); - gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); - gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); gSavedSettings.getControl("RenderAnisotropic")->getSignal()->connect(boost::bind(&handleAnisotropicChanged, _2)); gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); @@ -608,7 +611,6 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2)); gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2)); - gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _2)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2)); gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2)); gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index cb40af7061..0adb187dd2 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -260,6 +260,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.disableLights(); + //reset vertex buffers if needed + gPipeline.doResetVertexBuffers(); + stop_glerror(); // Don't draw if the window is hidden or minimized. diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index bb870f7651..affea90a15 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -35,7 +35,6 @@ #include "llcallfloater.h" #include "llfasttimerview.h" #include "llfloaterabout.h" -#include "llfloateranimpreview.h" #include "llfloaterauction.h" #include "llfloateravatar.h" #include "llfloateravatarpicker.h" @@ -49,6 +48,7 @@ #include "llfloaterbuyland.h" #include "llfloaterbulkpermission.h" #include "llfloaterbump.h" +#include "llfloaterbvhpreview.h" #include "llfloatercamera.h" #include "llfloaterdeleteenvpreset.h" #include "llfloaterdisplayname.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 "llfloatertelehub.h" #include "llfloatertestinspectors.h" #include "llfloatertestlistview.h" +#include "llfloatertexturefetchdebugger.h" #include "llfloatertools.h" #include "llfloatertos.h" #include "llfloatertopobjects.h" @@ -227,6 +227,11 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>); LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>); + + if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled")) + { + LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>); + } LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>); LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); @@ -294,10 +299,10 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterUIPreviewUtil::registerFloater(); - LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload"); + LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload"); + LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload"); LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload"); LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload"); - LLFloaterReg::add("upload_model_wizard", "floater_model_wizard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelWizard>); LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload"); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 163581ea7f..b47a41c44c 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -342,8 +342,8 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer<LLViewerInventoryItem>& ne void LLViewerInventoryItem::removeFromServer() { - llinfos << "Removing inventory item " << mUUID << " from server." - << llendl; + lldebugs << "Removing inventory item " << mUUID << " from server." + << llendl; LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1); gInventory.accountForUpdate(up); @@ -436,11 +436,6 @@ void LLViewerInventoryItem::fetchFromServer(void) const gAgent.sendReliableMessage(); } } - else - { - // *FIX: this can be removed after a bit. - llwarns << "request to fetch complete item" << llendl; - } } // virtual @@ -1462,6 +1457,7 @@ const std::string& LLViewerInventoryItem::getName() const class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> , public LLDestroyClass<LLFavoritesOrderStorage> { + LOG_CLASS(LLFavoritesOrderStorage); public: /** * Sets sort index for specified with LLUUID favorite landmark @@ -1620,10 +1616,18 @@ void LLFavoritesOrderStorage::load() void LLFavoritesOrderStorage::saveFavoritesSLURLs() { // Do not change the file if we are not logged in yet. - if (!LLLoginInstance::getInstance()->authSuccess()) return; + if (!LLLoginInstance::getInstance()->authSuccess()) + { + llwarns << "Cannot save favorites: not logged in" << llendl; + return; + } std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); - if (user_dir.empty()) return; + if (user_dir.empty()) + { + llwarns << "Cannot save favorites: empty user dir name" << llendl; + return; + } std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); llifstream in_file; @@ -1649,13 +1653,19 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs() slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); if (slurl_iter != mSLURLs.end()) { + lldebugs << "Saving favorite: idx=" << (*it)->getSortField() << ", SLURL=" << slurl_iter->second << ", value=" << value << llendl; value["slurl"] = slurl_iter->second; user_llsd[(*it)->getSortField()] = value; } + else + { + llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; + } } LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); + lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; fav_llsd[av_name.getLegacyName()] = user_llsd; llofstream file; @@ -1674,6 +1684,7 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); + lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; if (fav_llsd.has(av_name.getLegacyName())) { fav_llsd.erase(av_name.getLegacyName()); @@ -1706,6 +1717,7 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) { + lldebugs << "Saving landmark SLURL: " << slurl << llendl; mSLURLs[asset_id] = slurl; } diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 76f4e18c27..f029ae5302 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -63,7 +63,6 @@ extern PFNGLWEIGHTFVARBPROC glWeightfvARB; extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB; #endif -static LLPointer<LLVertexBuffer> sRenderBuffer = NULL; static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; @@ -577,7 +576,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { old_mode = mTexture->getAddressMode(); } - gGL.getTexUnit(diffuse_channel)->bind(mTexture.get()); gGL.getTexUnit(diffuse_channel)->bind(mTexture); gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index 0191f0cae8..dd5dae1dc1 100644 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -61,6 +61,7 @@ public: //----------------------------------------------------------------------------- class LLViewerJointMesh : public LLViewerJoint { + friend class LLVOAvatar; protected: LLColor4 mColor; // color value // LLColor4 mSpecular; // specular color (always white for now) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 046360e9e9..1eb4bedfaf 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -387,7 +387,6 @@ class LLViewerMediaMuteListObserver : public LLMuteListObserver static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver; static bool sViewerMediaMuteListObserverInitialized = false; -static bool sInWorldMediaDisabled = false; ////////////////////////////////////////////////////////////////////////////////////////// @@ -654,20 +653,6 @@ void LLViewerMedia::muteListChanged() ////////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::setInWorldMediaDisabled(bool disabled) -{ - sInWorldMediaDisabled = disabled; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerMedia::getInWorldMediaDisabled() -{ - return sInWorldMediaDisabled; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// static bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest) { bool result = false; @@ -1568,7 +1553,6 @@ LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() bool LLViewerMedia::hasInWorldMedia() { - if (sInWorldMediaDisabled) return false; impl_list::iterator iter = sViewerMediaImplList.begin(); impl_list::iterator end = sViewerMediaImplList.end(); // This should be quick, because there should be very few non-in-world-media impls @@ -1901,7 +1885,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } } - LL_WARNS_ONCE("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; + LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL; LLSD args; args["MIME_TYPE"] = media_type; LLNotificationsUtil::add("NoPlugin", args); @@ -3107,15 +3091,6 @@ bool LLViewerMediaImpl::isForcedUnloaded() const return true; } - if(sInWorldMediaDisabled) - { - // When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded. - if(!mUsedInUI) - { - return true; - } - } - // If this media's class is not supposed to be shown, unload if (!shouldShowBasedOnClass()) { @@ -3783,12 +3758,22 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const // If it is attached to an avatar and the pref is off, we shouldn't show it if (attached_to_another_avatar) - return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING); - + { + static LLCachedControl<bool> show_media_on_others(gSavedSettings, LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING); + return show_media_on_others; + } if (inside_parcel) - return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING); + { + static LLCachedControl<bool> show_media_within_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING); + + return show_media_within_parcel; + } else - return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING); + { + static LLCachedControl<bool> show_media_outside_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING); + + return show_media_outside_parcel; + } } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 15dcda59cf..fff5b3fc08 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -112,9 +112,6 @@ public: static F32 getVolume(); static void muteListChanged(); - static void setInWorldMediaDisabled(bool disabled); - static bool getInWorldMediaDisabled(); - static bool isInterestingEnough(const LLVOVolume* object, const F64 &object_interest); // Returns the priority-sorted list of all media impls. diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 99540ccce9..c9af6a2820 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -25,6 +25,11 @@ */ #include "llviewerprecompiledheaders.h" + +#ifdef INCLUDE_VLD +#include "vld.h" +#endif + #include "llviewermenu.h" // linden library includes @@ -88,6 +93,7 @@ #include "lltoolpie.h" #include "lltoolselectland.h" #include "lltrans.h" +#include "llviewerdisplay.h" //for gWindowResized #include "llviewergenericmessage.h" #include "llviewerhelp.h" #include "llviewermenufile.h" // init_menu_file() @@ -200,7 +206,7 @@ BOOL enable_take(); void handle_take(); void handle_object_show_inspector(); void handle_avatar_show_inspector(); -bool confirm_take(const LLSD& notification, const LLSD& response); +bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle); void handle_buy_object(LLSaleInfo sale_info); void handle_buy_contents(LLSaleInfo sale_info); @@ -214,7 +220,7 @@ void near_sit_down_point(BOOL success, void *); void velocity_interpolate( void* ); - +void handle_visual_leak_detector_toggle(void*); void handle_rebake_textures(void*); BOOL check_admin_override(void*); void handle_admin_override_toggle(void*); @@ -511,14 +517,6 @@ class LLAdvancedToggleConsole : public view_listener_t { toggle_visibility( (void*)static_cast<LLUICtrl*>(gDebugView->mDebugConsolep)); } - else if (gTextureSizeView && "texture size" == console_type) - { - toggle_visibility( (void*)gTextureSizeView ); - } - else if (gTextureCategoryView && "texture category" == console_type) - { - toggle_visibility( (void*)gTextureCategoryView ); - } else if ("fast timers" == console_type) { LLFloaterReg::toggleInstance("fast_timers"); @@ -551,14 +549,6 @@ class LLAdvancedCheckConsole : public view_listener_t { new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) ); } - else if (gTextureSizeView && "texture size" == console_type) - { - new_value = get_visibility( (void*)gTextureSizeView ); - } - else if (gTextureCategoryView && "texture category" == console_type) - { - new_value = get_visibility( (void*)gTextureCategoryView ); - } else if ("fast timers" == console_type) { new_value = LLFloaterReg::instanceVisible("fast_timers"); @@ -861,6 +851,73 @@ class LLAdvancedCheckFeature : public view_listener_t } }; +class LLAdvancedCheckDisplayTextureDensity : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + std::string mode = userdata.asString(); + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + return mode == "none"; + } + if (mode == "current") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_CURRENT; + } + else if (mode == "desired") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_DESIRED; + } + else if (mode == "full") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_FULL; + } + return false; + } +}; + +class LLAdvancedSetDisplayTextureDensity : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + std::string mode = userdata.asString(); + if (mode == "none") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == TRUE) + { + gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; + } + else if (mode == "current") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_CURRENT; + } + else if (mode == "desired") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY, true); + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_DESIRED; + } + else if (mode == "full") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_FULL; + } + return true; + } +}; + ////////////////// // INFO DISPLAY // @@ -975,6 +1032,10 @@ U32 info_display_from_string(std::string info_display) { return LLPipeline::RENDER_DEBUG_WIND_VECTORS; } + else if ("texel density" == info_display) + { + return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY; + } else { return 0; @@ -1113,6 +1174,7 @@ class LLAdvancedToggleWireframe : public view_listener_t bool handleEvent(const LLSD& userdata) { gUseWireframe = !(gUseWireframe); + gWindowResized = TRUE; LLPipeline::updateRenderDeferred(); gPipeline.resetVertexBuffers(); return true; @@ -2018,6 +2080,15 @@ class LLAdvancedToggleViewAdminOptions : public view_listener_t } }; +class LLAdvancedToggleVisualLeakDetector : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + handle_visual_leak_detector_toggle(NULL); + return true; + } +}; + class LLAdvancedCheckViewAdminOptions : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2231,6 +2302,14 @@ class LLDevelopSetLoggingLevel : public view_listener_t } }; +class LLDevelopTextureFetchDebugger : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + return gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); + } +}; + ////////////////// // ADMIN MENU // ////////////////// @@ -3444,6 +3523,35 @@ void handle_admin_override_toggle(void*) show_debug_menus(); } +void handle_visual_leak_detector_toggle(void*) +{ + static bool vld_enabled = false; + + if ( vld_enabled ) + { +#ifdef INCLUDE_VLD + // only works for debug builds (hard coded into vld.h) +#ifdef _DEBUG + // start with Visual Leak Detector turned off + VLDDisable(); +#endif // _DEBUG +#endif // INCLUDE_VLD + vld_enabled = false; + } + else + { +#ifdef INCLUDE_VLD + // only works for debug builds (hard coded into vld.h) + #ifdef _DEBUG + // start with Visual Leak Detector turned off + VLDEnable(); + #endif // _DEBUG +#endif // INCLUDE_VLD + + vld_enabled = true; + }; +} + void handle_god_mode(void*) { gAgent.requestEnterGodMode(); @@ -4405,7 +4513,10 @@ void handle_take() LLNotification::Params params("ConfirmObjectTakeLock"); params.payload(payload); - params.functor.function(confirm_take); + // MAINT-290 + // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez. + // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened + params.functor.function(boost::bind(confirm_take, _1, _2, LLSelectMgr::instance().getSelection())); if(locked_but_takeable_object || !you_own_everything) @@ -4458,7 +4569,7 @@ void handle_avatar_show_inspector() -bool confirm_take(const LLSD& notification, const LLSD& response) +bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(enable_take() && (option == 0)) @@ -5256,6 +5367,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 { @@ -6513,31 +6632,37 @@ class LLToolsSelectedScriptAction : public view_listener_t std::string action = userdata.asString(); bool mono = false; std::string msg, name; + std::string title; if (action == "compile mono") { name = "compile_queue"; mono = true; msg = "Recompile"; + title = LLTrans::getString("CompileQueueTitle"); } if (action == "compile lsl") { name = "compile_queue"; msg = "Recompile"; + title = LLTrans::getString("CompileQueueTitle"); } else if (action == "reset") { name = "reset_queue"; msg = "Reset"; + title = LLTrans::getString("ResetQueueTitle"); } else if (action == "start") { name = "start_queue"; msg = "SetRunning"; + title = LLTrans::getString("RunQueueTitle"); } else if (action == "stop") { name = "stop_queue"; msg = "SetRunningNot"; + title = LLTrans::getString("NotRunQueueTitle"); } LLUUID id; id.generate(); @@ -6546,6 +6671,7 @@ class LLToolsSelectedScriptAction : public view_listener_t { queue->setMono(mono); queue_actions(queue, msg); + queue->setTitle(title); } else { @@ -7281,12 +7407,6 @@ class LLToolsUseSelectionForGrid : public view_listener_t } func; LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func); LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT); - - LLFloaterBuildOptions* build_options_floater = LLFloaterReg::getTypedInstance<LLFloaterBuildOptions>("build_options"); - if (build_options_floater && build_options_floater->getVisible()) - { - build_options_floater->setGridMode(GRID_MODE_REF_OBJECT); - } return true; } }; @@ -8040,6 +8160,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"); @@ -8120,6 +8243,10 @@ void initialize_menus() //// Advanced > Render > Features view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature"); view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature"); + + view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity"); + view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity"); + // Advanced > Render > Info Displays view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay"); view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay"); @@ -8243,12 +8370,17 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions"); view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions"); view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions"); + view_listener_t::addMenu(new LLAdvancedToggleVisualLeakDetector(), "Advanced.ToggleVisualLeakDetector"); + view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus"); view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus"); // Develop >Set logging level view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel"); view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel"); + + //Develop (Texture Fetch Debug Console) + view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger"); // Admin >Object view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 7e830e14bf..dc2ea4bd1f 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -183,7 +183,7 @@ void LLFilePickerThread::clearDead() #if LL_WINDOWS static std::string SOUND_EXTENSIONS = "wav"; static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png"; -static std::string ANIM_EXTENSIONS = "bvh"; +static std::string ANIM_EXTENSIONS = "bvh anim"; #ifdef _CORY_TESTING static std::string GEOMETRY_EXTENSIONS = "slg"; #endif @@ -385,7 +385,14 @@ class LLFileUploadAnim : public view_listener_t const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_ANIM); if (!filename.empty()) { - LLFloaterReg::showInstance("upload_anim", LLSD(filename)); + if (filename.rfind(".anim") != std::string::npos) + { + LLFloaterReg::showInstance("upload_anim_anim", LLSD(filename)); + } + else + { + LLFloaterReg::showInstance("upload_anim_bvh", LLSD(filename)); + } } return true; } @@ -527,8 +534,22 @@ class LLFileTakeSnapshotToDisk : public view_listener_t FALSE)) { gViewerWindow->playSnapshotAnimAndSound(); - - LLPointer<LLImageFormatted> formatted = new LLImagePNG; + LLPointer<LLImageFormatted> formatted; + LLFloaterSnapshot::ESnapshotFormat fmt = (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); + switch (fmt) + { + case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); + break; + default: + llwarns << "Unknown local snapshot format: " << fmt << llendl; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + formatted = new LLImagePNG; + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + formatted = new LLImageBMP; + break; + } formatted->enableOverSize() ; formatted->encode(raw, 0); formatted->disableOverSize() ; @@ -785,6 +806,11 @@ LLUUID upload_new_resource( upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args); return LLUUID(); } + else if (exten == "anim") + { + asset_type = LLAssetType::AT_ANIMATION; + filename = src_filename; + } else { // Unknown extension @@ -949,11 +975,12 @@ void upload_done_callback( args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); LLNotificationsUtil::add("CannotUploadReason", args); } + + delete data; + data = NULL; } LLUploadDialog::modalUploadFinished(); - delete data; - data = NULL; // *NOTE: This is a pretty big hack. What this does is check the // file picker if there are any more pending uploads. If so, diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 536d3d2056..1813611c35 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -135,6 +135,7 @@ extern BOOL gDebugClicks; // function prototypes bool check_offer_throttle(const std::string& from_name, bool check_only); +bool check_asset_previewable(const LLAssetType::EType asset_type); static void process_money_balance_reply_extended(LLMessageSystem* msg); //inventory offer throttle globals @@ -155,7 +156,8 @@ const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] = "AddAndRemoveJoints", "ChangePermissions", "TrackYourCamera", - "ControlYourCamera" + "ControlYourCamera", + "TeleportYourAgent" }; const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = @@ -170,7 +172,8 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = FALSE, // AddAndRemoveJoints FALSE, // ChangePermissions FALSE, // TrackYourCamera, - FALSE // ControlYourCamera + FALSE, // ControlYourCamera + FALSE // TeleportYourAgent }; bool friendship_offer_callback(const LLSD& notification, const LLSD& response) @@ -1064,7 +1067,9 @@ public: // If we now try to remove the inventory item, it will cause a nested // notifyObservers() call, which won't work. // So defer moving the item to trash until viewer gets idle (in a moment). - LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeItem, &gInventory, mObjectID)); + // Use removeObject() rather than removeItem() because at this level, + // the object could be either an item or a folder. + LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeObject, &gInventory, mObjectID)); gInventory.removeObserver(this); delete this; } @@ -1147,7 +1152,18 @@ bool check_offer_throttle(const std::string& from_name, bool check_only) } } } - + +// Return "true" if we have a preview method for that asset type, "false" otherwise +bool check_asset_previewable(const LLAssetType::EType asset_type) +{ + return (asset_type == LLAssetType::AT_NOTECARD) || + (asset_type == LLAssetType::AT_LANDMARK) || + (asset_type == LLAssetType::AT_TEXTURE) || + (asset_type == LLAssetType::AT_ANIMATION) || + (asset_type == LLAssetType::AT_SCRIPT) || + (asset_type == LLAssetType::AT_SOUND); +} + void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name) { for (uuid_vec_t::const_iterator obj_iter = objects.begin(); @@ -1171,7 +1187,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam // Either an inventory item or a category. const LLInventoryItem* item = dynamic_cast<const LLInventoryItem*>(obj); - if (item) + if (item && check_asset_previewable(asset_type)) { //////////////////////////////////////////////////////////////////////////////// // Special handling for various types. @@ -1246,6 +1262,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam LLFloaterReg::showInstance("preview_sound", LLSD(obj_id), take_focus); break; default: + LL_DEBUGS("Messaging") << "No preview method for previewable asset type : " << LLAssetType::lookupHumanReadable(asset_type) << LL_ENDL; break; } } @@ -2360,8 +2377,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; bool mute_im = is_muted; - if(accept_im_from_only_friend&&!is_friend) + if (accept_im_from_only_friend && !is_friend) { + if (!gIMMgr->isNonFriendSessionNotified(session_id)) + { + std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); + gIMMgr->addMessage(session_id, from_id, name, message); + gIMMgr->addNotifiedNonFriendSessionID(session_id); + } + mute_im = true; } if (!mute_im || is_linden) @@ -2682,7 +2706,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_SESSION_SEND: { - if (!is_linden && is_busy) + if (is_busy) { return; } @@ -5825,6 +5849,16 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) S32 orig = notification["payload"]["questions"].asInteger(); S32 new_questions = orig; + if (response["Details"]) + { + // respawn notification... + LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]); + + // ...with description on top + LLNotificationsUtil::add("DebitPermissionDetails"); + return false; + } + // check whether permissions were granted or denied BOOL allowed = TRUE; // the "yes/accept" button is the first button in the template, making it button 0 @@ -5882,14 +5916,6 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(item_id)); } - if (response["Details"]) - { - // respawn notification... - LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]); - - // ...with description on top - LLNotificationsUtil::add("DebitPermissionDetails"); - } return false; } static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb); @@ -5959,16 +5985,21 @@ void process_script_question(LLMessageSystem *msg, void **user_data) args["OBJECTNAME"] = object_name; args["NAME"] = LLCacheName::cleanFullName(owner_name); + BOOL has_not_only_debit = questions ^ LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_DEBIT]; // check the received permission flags against each permission for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++) { if (questions & LSCRIPTRunTimePermissionBits[i]) { count++; - script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n"; // check whether permission question should cause special caution dialog caution |= (SCRIPT_QUESTION_IS_CAUTION[i]); + + if (("ScriptTakeMoney" == SCRIPT_QUESTIONS[i]) && has_not_only_debit) + continue; + + script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n"; } } args["QUESTIONS"] = script_question; @@ -5984,6 +6015,10 @@ void process_script_question(LLMessageSystem *msg, void **user_data) // check whether cautions are even enabled or not if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) { + if (caution) + { + args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n\n" + script_question : ""; + } // display the caution permissions prompt LLNotificationsUtil::add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload); } @@ -6832,12 +6867,14 @@ void process_covenant_reply(LLMessageSystem* msg, void**) LLPanelEstateCovenant::updateEstateName(estate_name); LLPanelLandCovenant::updateEstateName(estate_name); + LLPanelEstateInfo::updateEstateName(estate_name); LLFloaterBuyLand::updateEstateName(estate_name); std::string owner_name = LLSLURL("agent", estate_owner_id, "inspect").getSLURLString(); LLPanelEstateCovenant::updateEstateOwnerName(owner_name); LLPanelLandCovenant::updateEstateOwnerName(owner_name); + LLPanelEstateInfo::updateEstateOwnerName(owner_name); LLFloaterBuyLand::updateEstateOwnerName(owner_name); LLPanelPlaceProfile* panel = LLFloaterSidePanelContainer::getPanel<LLPanelPlaceProfile>("places", "panel_place_profile"); diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index f326a5b29b..594c22ed9c 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -35,6 +35,7 @@ #include "message.h" #include "stdenums.h" #include "llnotifications.h" +#include "llextendedstatus.h" #include <boost/function.hpp> #include <boost/signals2.hpp> diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 37fb77a10a..da72f2fdac 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -143,7 +143,10 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco } else { - gAgentAvatarp->updateRegion(regionp); + if (isAgentAvatarValid()) + { + gAgentAvatarp->updateRegion(regionp); + } } res = gAgentAvatarp; } @@ -874,6 +877,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, LLMemType mt(LLMemType::MTYPE_OBJECT); U32 retval = 0x0; + // If region is removed from the list it is also deleted. + if (!LLWorld::instance().isRegionListed(mRegionp)) + { + llwarns << "Updating object in an invalid region" << llendl; + return retval; + } + // Coordinates of objects on simulators are region-local. U64 region_handle; mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); @@ -2379,10 +2389,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); @@ -3475,7 +3486,8 @@ LLNameValue *LLViewerObject::getNVPair(const std::string& name) const void LLViewerObject::updatePositionCaches() const { - if(mRegionp) + // If region is removed from the list it is also deleted. + if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) { if (!isRoot()) { @@ -3492,7 +3504,8 @@ void LLViewerObject::updatePositionCaches() const const LLVector3d LLViewerObject::getPositionGlobal() const { - if(mRegionp) + // If region is removed from the list it is also deleted. + if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) { LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); @@ -3511,7 +3524,8 @@ const LLVector3d LLViewerObject::getPositionGlobal() const const LLVector3 &LLViewerObject::getPositionAgent() const { - if (mRegionp) + // If region is removed from the list it is also deleted. + if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) { if (mDrawable.notNull() && (!mDrawable->isRoot() && getParent())) { diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 6912faa9ec..54ccfb9aae 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -91,8 +91,9 @@ extern LLPipeline gPipeline; // Statics for object lookup tables. U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check. -std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex; +std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex; std::map<U64, LLUUID> LLViewerObjectList::sIndexAndLocalIDToUUID; +LLStat LLViewerObjectList::sCacheHitRate("object_cache_hits", 128); LLViewerObjectList::LLViewerObjectList() { @@ -542,6 +543,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } justCreated = TRUE; mNumNewObjects++; + sCacheHitRate.addValue(cached ? 100.f : 0.f); + } diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index c5f2a2c1ee..64925f46ae 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -192,6 +192,8 @@ protected: std::vector<OrphanInfo> mOrphanChildren; // UUID's of orphaned objects S32 mNumOrphans; + static LLStat sCacheHitRate; + typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t; vobj_list_t mObjects; diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index f738b84bb9..6c8a827ba3 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -57,6 +57,8 @@ #include "lldeleteutils.h" #include "imageids.h" #include "indra_constants.h" +#include "llinitparam.h" + //#include "linden_common.h" //#include "llpreprocessor.h" #include "llallocator.h" @@ -124,7 +126,5 @@ // Library includes from llmessage project #include "llcachename.h" -// Library includes from llxuixml -#include "llinitparam.h" #endif diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5de363e03c..10c61c01d5 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -363,6 +363,12 @@ void LLViewerShaderMgr::setShaders() //NEVER use more than 16 texture channels (work around for prevalent driver bug) LLGLSLShader::sIndexedTextureChannels = llmin(LLGLSLShader::sIndexedTextureChannels, 16); + if (gGLManager.mGLSLVersionMajor < 1 || + (gGLManager.mGLSLVersionMajor == 1 && gGLManager.mGLSLVersionMinor <= 20)) + { //NEVER use indexed texture rendering when GLSL version is 1.20 or earlier + LLGLSLShader::sIndexedTextureChannels = 1; + } + reentrance = true; if (LLRender::sGLCoreProfile) @@ -407,6 +413,8 @@ void LLViewerShaderMgr::setShaders() // Shaders LL_INFOS("ShaderLoading") << "\n~~~~~~~~~~~~~~~~~~\n Loading Shaders:\n~~~~~~~~~~~~~~~~~~" << LL_ENDL; + LL_INFOS("ShaderLoading") << llformat("Using GLSL %d.%d", gGLManager.mGLSLVersionMajor, gGLManager.mGLSLVersionMinor) << llendl; + for (S32 i = 0; i < SHADER_COUNT; i++) { mVertexShaderLevel[i] = 0; @@ -416,6 +424,7 @@ void LLViewerShaderMgr::setShaders() LLGLSLShader::sNoFixedFunction = false; LLVertexBuffer::unbind(); if (LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") + && (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 10) && gSavedSettings.getBOOL("VertexShaderEnable")) { //using shaders, disable fixed function @@ -730,7 +739,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() vector< pair<string, S32> > shaders; shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); + shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); shaders.push_back( make_pair( "lighting/lightFuncV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); shaders.push_back( make_pair( "lighting/sumLightsV.glsl", sum_lights_class ) ); @@ -741,7 +750,10 @@ BOOL LLViewerShaderMgr::loadBasicShaders() shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) ); shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) ); - shaders.push_back( make_pair( "objects/indexedTextureV.glsl", 1 ) ); + if (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30) + { + shaders.push_back( make_pair( "objects/indexedTextureV.glsl", 1 ) ); + } shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. @@ -758,11 +770,11 @@ BOOL LLViewerShaderMgr::loadBasicShaders() // (in order of shader function call depth for reference purposes, deepest level first) shaders.clear(); - S32 ch = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + S32 ch = 1; - if (gGLManager.mGLVersion < 3.1f) - { //force to 1 texture index channel for old drivers - ch = 1; + if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) + { //use indexed texture rendering for GLSL >= 1.30 + ch = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); } std::vector<S32> index_channels; @@ -1102,19 +1114,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader"; + gDeferredSkinnedAlphaProgram.mFeatures.atmosphericHelpers = true; gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true; gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true; gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true; - gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true; + gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = false; + gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = false; gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true; gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true; gDeferredSkinnedAlphaProgram.mShaderFiles.clear(); gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL); + + // Hack to include uniforms for lighting without linking in lighting file + gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true; } if (success) @@ -1200,6 +1218,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { std::string fragment; + std::string vertex = "deferred/sunLightV.glsl"; if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { @@ -1208,11 +1227,15 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() else { fragment = "deferred/sunLightF.glsl"; + if (mVertexShaderLevel[SHADER_DEFERRED] == 1) + { //no shadows, no SSAO, no frag coord + vertex = "deferred/sunLightNoFragCoordV.glsl"; + } } gDeferredSunProgram.mName = "Deferred Sun Shader"; gDeferredSunProgram.mShaderFiles.clear(); - gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER_ARB)); gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredSunProgram.createShader(NULL, NULL); @@ -1231,11 +1254,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredAlphaProgram.mName = "Deferred Alpha Shader"; - gDeferredAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAlphaProgram.mFeatures.atmosphericHelpers = true; + gDeferredAlphaProgram.mFeatures.calculatesLighting = false; gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true; gDeferredAlphaProgram.mFeatures.hasGamma = true; gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; - gDeferredAlphaProgram.mFeatures.hasLighting = true; + gDeferredAlphaProgram.mFeatures.hasLighting = false; gDeferredAlphaProgram.mFeatures.isAlphaLighting = true; gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels if (mVertexShaderLevel[SHADER_DEFERRED] < 1) @@ -1251,7 +1275,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAlphaProgram.createShader(NULL, NULL); + + // Hack + gDeferredAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAlphaProgram.mFeatures.hasLighting = true; } if (success) @@ -1394,19 +1423,24 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredAvatarAlphaProgram.mName = "Avatar Alpha Shader"; + gDeferredAvatarAlphaProgram.mFeatures.atmosphericHelpers = true; gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true; - gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = false; gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true; gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true; gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; - gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; + gDeferredAvatarAlphaProgram.mFeatures.hasLighting = false; gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true; gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true; gDeferredAvatarAlphaProgram.mShaderFiles.clear(); - gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaNoColorV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedNoColorF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarAlphaProgram.createShader(NULL, &mAvatarUniforms); + + gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; } if (success) @@ -1423,7 +1457,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredPostProgram.mName = "Deferred Post Shader"; gDeferredPostProgram.mShaderFiles.clear(); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredPostProgram.createShader(NULL, NULL); @@ -1433,7 +1467,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredCoFProgram.mName = "Deferred CoF Shader"; gDeferredCoFProgram.mShaderFiles.clear(); - gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredCoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredCoFProgram.createShader(NULL, NULL); @@ -1443,7 +1477,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredDoFCombineProgram.mName = "Deferred DoFCombine Shader"; gDeferredDoFCombineProgram.mShaderFiles.clear(); - gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredDoFCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredDoFCombineProgram.createShader(NULL, NULL); @@ -1453,7 +1487,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredPostNoDoFProgram.mName = "Deferred Post Shader"; gDeferredPostNoDoFProgram.mShaderFiles.clear(); - gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredPostNoDoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredPostNoDoFProgram.createShader(NULL, NULL); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index c88122f22c..497e95c5e3 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -860,3 +860,110 @@ void send_stats() LLHTTPClient::post(url, body, new ViewerStatsResponder()); } +LLFrameTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name) +{ + phase_map_t::iterator iter = mPhaseMap.find(phase_name); + if (iter == mPhaseMap.end()) + { + LLFrameTimer timer; + mPhaseMap[phase_name] = timer; + } + LLFrameTimer& timer = mPhaseMap[phase_name]; + return timer; +} + +void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name) +{ + LLFrameTimer& timer = getPhaseTimer(phase_name); + lldebugs << "startPhase " << phase_name << llendl; + timer.unpause(); +} + +void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name) +{ + phase_map_t::iterator iter = mPhaseMap.find(phase_name); + if (iter != mPhaseMap.end()) + { + if (iter->second.getStarted()) + { + // Going from started to paused state - record stats. + recordPhaseStat(phase_name,iter->second.getElapsedTimeF32()); + } + lldebugs << "stopPhase " << phase_name << llendl; + iter->second.pause(); + } + else + { + lldebugs << "stopPhase " << phase_name << " is not started, no-op" << llendl; + } +} + +void LLViewerStats::PhaseMap::stopAllPhases() +{ + for (phase_map_t::iterator iter = mPhaseMap.begin(); + iter != mPhaseMap.end(); ++iter) + { + const std::string& phase_name = iter->first; + if (iter->second.getStarted()) + { + // Going from started to paused state - record stats. + recordPhaseStat(phase_name,iter->second.getElapsedTimeF32()); + } + lldebugs << "stopPhase (all) " << phase_name << llendl; + iter->second.pause(); + } +} + +void LLViewerStats::PhaseMap::clearPhases() +{ + lldebugs << "clearPhases" << llendl; + + mPhaseMap.clear(); +} + +LLSD LLViewerStats::PhaseMap::dumpPhases() +{ + LLSD result; + for (phase_map_t::iterator iter = mPhaseMap.begin(); iter != mPhaseMap.end(); ++iter) + { + const std::string& phase_name = iter->first; + result[phase_name]["completed"] = !(iter->second.getStarted()); + result[phase_name]["elapsed"] = iter->second.getElapsedTimeF32(); +#if 0 // global stats for each phase seem like overkill here + phase_stats_t::iterator stats_iter = sPhaseStats.find(phase_name); + if (stats_iter != sPhaseStats.end()) + { + result[phase_name]["stats"] = stats_iter->second.getData(); + } +#endif + } + return result; +} + +// static initializer +//static +LLViewerStats::phase_stats_t LLViewerStats::PhaseMap::sStats; + +LLViewerStats::PhaseMap::PhaseMap() +{ +} + +// static +LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name) +{ + phase_stats_t::iterator it = sStats.find(phase_name); + if (it == sStats.end()) + { + LLViewerStats::StatsAccumulator new_stats; + sStats[phase_name] = new_stats; + } + return sStats[phase_name]; +} + +// static +void LLViewerStats::PhaseMap::recordPhaseStat(const std::string& phase_name, F32 value) +{ + LLViewerStats::StatsAccumulator& stats = getPhaseStats(phase_name); + stats.push(value); +} + diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index f91a1241fe..750d963f69 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -244,7 +244,7 @@ public: inline F32 getStdDev() const { const F32 mean = getMean(); - return (mCount == 0) ? 0.f : sqrt( mSumOfSquares/mCount - (mean * mean) ); + return (mCount < 2) ? 0.f : sqrt(llmax(0.f,mSumOfSquares/mCount - (mean * mean))); } inline U32 getCount() const @@ -274,7 +274,28 @@ public: }; StatsAccumulator mAgentPositionSnaps; - + + // Phase tracking (originally put in for avatar rezzing), tracking + // progress of active/completed phases for activities like outfit changing. + typedef std::map<std::string,LLFrameTimer> phase_map_t; + typedef std::map<std::string,StatsAccumulator> phase_stats_t; + class PhaseMap + { + private: + phase_map_t mPhaseMap; + static phase_stats_t sStats; + public: + PhaseMap(); + LLFrameTimer& getPhaseTimer(const std::string& phase_name); + void startPhase(const std::string& phase_name); + void stopPhase(const std::string& phase_name); + void stopAllPhases(); + void clearPhases(); + LLSD dumpPhases(); + static StatsAccumulator& getPhaseStats(const std::string& phase_name); + static void recordPhaseStat(const std::string& phase_name, F32 value); + }; + private: F64 mStats[ST_COUNT]; diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index b41ed00f17..99102309a1 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -187,7 +187,7 @@ public: else { width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str()); - height = llmax(mImage->getHeight(), llceil(mStyle->getFont()->getLineHeight())); + height = llmax(mImage->getHeight(), mStyle->getFont()->getLineHeight()); } return false; } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 61236edc86..d844aeb12a 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -67,6 +67,7 @@ // statics LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL; LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL; +LLPointer<LLViewerTexture> LLViewerTexture::sCheckerBoardImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL; @@ -87,6 +88,7 @@ S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0; S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0; S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ; S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ; +F32 LLViewerTexture::sCameraMovingBias = 0.0f ; S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ; const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ; @@ -96,6 +98,9 @@ S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ; BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ; F32 LLViewerTexture::sCurrentTime = 0.0f ; BOOL LLViewerTexture::sUseTextureAtlas = FALSE ; +F32 LLViewerTexture::sTexelPixelRatio = 1.0f; + +LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by @@ -175,7 +180,12 @@ LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id) } return tex ; } - + +LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id) +{ + return gTextureList.findImage(id); +} + LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id) { return LLViewerMediaTexture::findMediaTexture(media_id) ; @@ -347,6 +357,21 @@ void LLViewerTextureManager::init() LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI); LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ; + image_raw = new LLImageRaw(32,32,3); + data = image_raw->getData(); + + for (S32 i = 0; i < (32*32*3); i+=3) + { + S32 x = (i % (32*3)) / (3*16); + S32 y = i / (32*3*16); + U8 color = ((x + y) % 2) * 255; + data[i] = color; + data[i+1] = color; + data[i+2] = color; + } + + LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); + LLViewerTexture::initClass() ; if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) @@ -367,6 +392,7 @@ void LLViewerTextureManager::cleanup() LLImageGL::sDefaultGLTexture = NULL ; LLViewerTexture::sNullImagep = NULL; LLViewerTexture::sBlackImagep = NULL; + LLViewerTexture::sCheckerBoardImagep = NULL; LLViewerFetchedTexture::sDefaultImagep = NULL; LLViewerFetchedTexture::sSmokeImagep = NULL; LLViewerFetchedTexture::sMissingAssetImagep = NULL; @@ -383,11 +409,7 @@ void LLViewerTextureManager::cleanup() void LLViewerTexture::initClass() { LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ; - - if(gAuditTexture) - { - LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ; - } + sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio"); } // static @@ -534,7 +556,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); - sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ; + sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1); + sCameraMovingDiscardBias = (S8)(sCameraMovingBias); LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; @@ -655,10 +678,6 @@ void LLViewerTexture::setBoostLevel(S32 level) { setNoDelete() ; } - if(gAuditTexture) - { - setCategory(mBoostLevel); - } } } @@ -712,6 +731,7 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co mNeedsGLTexture = TRUE ; } + virtual_size *= sTexelPixelRatio; if(!mMaxVirtualSizeResetCounter) { //flag to reset the values because the old values are used. @@ -1287,6 +1307,7 @@ void LLViewerFetchedTexture::cleanup() mCachedRawDiscardLevel = -1 ; mCachedRawImageReady = FALSE ; mSavedRawImage = NULL ; + mSavedRawDiscardLevel = -1; } void LLViewerFetchedTexture::setForSculpt() @@ -1880,6 +1901,8 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching() bool LLViewerFetchedTexture::updateFetch() { static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); + static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold"); + static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost"); if(textures_decode_disabled) { return false ; @@ -2042,18 +2065,24 @@ bool LLViewerFetchedTexture::updateFetch() // make_request = false; //} - if(make_request) + if (make_request) { - //load the texture progressively. + // Load the texture progressively: we try not to rush to the desired discard too fast. + // If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps + // This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ; - if(current_discard < 0) + if (current_discard < 0) { desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level); } - else + else if (LLViewerTexture::sCameraMovingBias < sCameraMotionThreshold) { - desired_discard = llmax(desired_discard, current_discard - delta_level); + desired_discard = llmax(desired_discard, current_discard - sCameraMotionBoost); } + else + { + desired_discard = llmax(desired_discard, current_discard - delta_level); + } if (mIsFetching) { @@ -2121,6 +2150,30 @@ bool LLViewerFetchedTexture::updateFetch() return mIsFetching ? true : false; } +void LLViewerFetchedTexture::clearFetchedResults() +{ + llassert_always(!mNeedsCreateTexture && !mIsFetching); + + cleanup(); + destroyGLTexture(); + + if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate + { + mGLTexturep->forceToInvalidateGLTexture(); + } +} + +void LLViewerFetchedTexture::forceToDeleteRequest() +{ + if (mHasFetcher) + { + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + mHasFetcher = FALSE; + mIsFetching = FALSE ; + resetTextureStats(); + } +} + void LLViewerFetchedTexture::setIsMissingAsset() { if (mUrl.empty()) @@ -3290,10 +3343,14 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL sMediaMap.insert(std::make_pair(id, this)); mGLTexturep = gl_image ; + if(mGLTexturep.isNull()) { generateGLTexture() ; } + + mGLTexturep->setAllowCompression(false); + mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ; mIsPlaying = FALSE ; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index b96441127d..f1105c3705 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -139,6 +139,7 @@ public: OTHER, MAX_GL_IMAGE_CATEGORY }; + static S32 getTotalNumOfCategories() ; static S32 getIndexFromCategory(S32 category) ; static S32 getCategoryFromIndex(S32 index) ; @@ -263,6 +264,9 @@ protected: void reorganizeVolumeList() ; void setTexelsPerImage(); private: + friend class LLBumpImageList; + friend class LLUIImageList; + //note: do not make this function public. /*virtual*/ LLImageGL* getGLTexture() const ; virtual void switchToCachedImage(); @@ -309,6 +313,7 @@ protected: } LLGLTextureState; LLGLTextureState mTextureState ; + static F32 sTexelPixelRatio; public: static const U32 sCurrentFileVersion; static S32 sImageCount; @@ -323,6 +328,7 @@ public: static S32 sMaxTotalTextureMemInMegaBytes; static S32 sMaxDesiredTextureMemInBytes ; static S8 sCameraMovingDiscardBias; + static F32 sCameraMovingBias; static S32 sMaxSculptRez ; static S32 sMinLargeImageSize ; static S32 sMaxSmallImageSize ; @@ -330,8 +336,19 @@ public: static F32 sCurrentTime ; static BOOL sUseTextureAtlas ; + enum EDebugTexels + { + DEBUG_TEXELS_OFF, + DEBUG_TEXELS_CURRENT, + DEBUG_TEXELS_DESIRED, + DEBUG_TEXELS_FULL + }; + + static EDebugTexels sDebugTexelsMode; + static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects. static LLPointer<LLViewerTexture> sBlackImagep; // Texture to show NOTHING (pure black) + static LLPointer<LLViewerTexture> sCheckerBoardImagep; // Texture to show NOTHING (pure black) }; @@ -420,6 +437,8 @@ public: bool updateFetch(); + void clearFetchedResults(); //clear all fetched results, for debug use. + // Override the computation of discard levels if we know the exact output // size of the image. Used for UI textures to not decode, even if we have // more data. @@ -478,6 +497,7 @@ public: BOOL hasFetcher() const { return mHasFetcher;} void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} + void forceToDeleteRequest(); protected: /*virtual*/ void switchToCachedImage(); S32 getCurrentDiscardLevelForFetching() ; @@ -687,6 +707,7 @@ public: //"find-texture" just check if the texture exists, if yes, return it, otherwise return null. // static LLViewerTexture* findTexture(const LLUUID& id) ; + static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id) ; static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ; static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 089f45ca89..528e0080b7 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -58,6 +58,7 @@ #include "pipeline.h" #include "llappviewer.h" #include "llxuiparser.h" +#include "llagent.h" //////////////////////////////////////////////////////////////////////////// @@ -597,6 +598,12 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_STATS("Stats"); void LLViewerTextureList::updateImages(F32 max_time) { + if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) + { + clearFetchingRequests(); + return; + } + LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec()); LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages); @@ -659,6 +666,24 @@ void LLViewerTextureList::updateImages(F32 max_time) } } +void LLViewerTextureList::clearFetchingRequests() +{ + if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) + { + return; + } + + for (image_priority_list_t::iterator iter = mImageList.begin(); + iter != mImageList.end(); ++iter) + { + LLViewerFetchedTexture* image = *iter; + if(image->hasFetcher()) + { + image->forceToDeleteRequest() ; + } + } +} + void LLViewerTextureList::updateImagesDecodePriorities() { // Update the decode priority for N images each frame @@ -1030,7 +1055,6 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage { raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C(); - compressedImage->setRate(0.f); if (gSavedSettings.getBOOL("LosslessJ2CUpload") && (raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)) @@ -1432,6 +1456,9 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st imagep->setAddressMode(LLTexUnit::TAM_CLAMP); + //don't compress UI images + imagep->getGLTexture()->setAllowCompression(false); + //all UI images are non-deletable imagep->setNoDelete(); diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index e0a362596d..e89997fe28 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -65,6 +65,7 @@ class LLViewerTextureList friend class LLTextureView; friend class LLViewerTextureManager; + friend class LLLocalBitmap; public: static BOOL createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec); @@ -109,6 +110,8 @@ public: void doPreloadImages(); void doPrefetchImages(); + void clearFetchingRequests(); + static S32 getMinVideoRamSetting(); static S32 getMaxVideoRamSetting(bool get_recommended = false); @@ -163,7 +166,7 @@ private: // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host) - { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } + { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } public: typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8a713ae22c..39e330ad66 100644..100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -27,9 +27,6 @@ #include "llviewerprecompiledheaders.h" #include "llviewerwindow.h" -#if LL_WINDOWS -#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally -#endif // system library includes #include <stdio.h> @@ -49,7 +46,6 @@ #include "llviewquery.h" #include "llxmltree.h" #include "llslurl.h" -//#include "llviewercamera.h" #include "llrender.h" #include "llvoiceclient.h" // for push-to-talk button handling @@ -538,7 +534,10 @@ public: } - addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024))); + addText(xpos, ypos, llformat("%d MB Index Data (%d MB Pooled, %d KIndices)", LLVertexBuffer::sAllocatedIndexBytes/(1024*1024), LLVBOPool::sIndexBytesPooled/(1024*1024), LLVertexBuffer::sIndexCount/1024)); + ypos += y_inc; + + addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled, %d KVerts)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024), LLVertexBuffer::sVertexCount/1024)); ypos += y_inc; addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount)); @@ -746,40 +745,41 @@ public: if (gSavedSettings.getBOOL("DebugShowTextureInfo")) { LLViewerObject* objectp = NULL ; - //objectp = = gAgentCamera.getFocusObject(); LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); if (nodep) { - objectp = nodep->getObject(); + objectp = nodep->getObject(); } + if (objectp && !objectp->isDead()) { S32 num_faces = objectp->mDrawable->getNumFaces() ; - + std::set<LLViewerFetchedTexture*> tex_list; + for(S32 i = 0 ; i < num_faces; i++) { LLFace* facep = objectp->mDrawable->getFace(i) ; if(facep) - { - //addText(xpos, ypos, llformat("ts_min: %.3f ts_max: %.3f tt_min: %.3f tt_max: %.3f", facep->mTexExtents[0].mV[0], facep->mTexExtents[1].mV[0], - // facep->mTexExtents[0].mV[1], facep->mTexExtents[1].mV[1])); - //ypos += y_inc; - - addText(xpos, ypos, llformat("v_size: %.3f: p_size: %.3f", facep->getVirtualSize(), facep->getPixelArea())); - ypos += y_inc; - - //const LLTextureEntry *tep = facep->getTextureEntry(); - //if(tep) - //{ - // addText(xpos, ypos, llformat("scale_s: %.3f: scale_t: %.3f", tep->mScaleS, tep->mScaleT)) ; - // ypos += y_inc; - //} - - LLViewerTexture* tex = facep->getTexture() ; + { + LLViewerFetchedTexture* tex = dynamic_cast<LLViewerFetchedTexture*>(facep->getTexture()) ; if(tex) { - addText(xpos, ypos, llformat("ID: %s v_size: %.3f", tex->getID().asString().c_str(), tex->getMaxVirtualSize())); + if(tex_list.find(tex) != tex_list.end()) + { + continue ; //already displayed. + } + tex_list.insert(tex); + + std::string uuid_str; + tex->getID().toString(uuid_str); + uuid_str = uuid_str.substr(0,7); + + addText(xpos, ypos, llformat("ID: %s v_size: %.3f", uuid_str.c_str(), tex->getMaxVirtualSize())); + ypos += y_inc; + + addText(xpos, ypos, llformat("discard level: %d desired level: %d Missing: %s", tex->getDiscardLevel(), + tex->getDesiredDiscardLevel(), tex->isMissingAsset() ? "Y" : "N")); ypos += y_inc; } } @@ -1540,14 +1540,14 @@ LLViewerWindow::LLViewerWindow(const Params& p) mResDirty(false), mStatesDirty(false), mCurrResolutionIndex(0), + mProgressView(NULL) +{ // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to // pass its value right now. Instead, pass it a nullary function that // will, when we later need it, return the value of gKeyboard. // boost::lambda::var() constructs such a functor on the fly. - mWindowListener(new LLWindowListener(this, boost::lambda::var(gKeyboard))), - mViewerWindowListener(new LLViewerWindowListener(this)), - mProgressView(NULL) -{ + mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); + mViewerWindowListener.reset(new LLViewerWindowListener(this)); LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); @@ -2021,6 +2021,12 @@ void LLViewerWindow::shutdownGL() gSky.cleanup(); stop_glerror(); + llinfos << "Cleaning up pipeline" << llendl; + gPipeline.cleanup(); + stop_glerror(); + + //MUST clean up pipeline before cleaning up wearables + llinfos << "Cleaning up wearables" << llendl; LLWearableList::instance().cleanup() ; gTextureList.shutdown(); @@ -2031,10 +2037,6 @@ void LLViewerWindow::shutdownGL() LLWorldMapView::cleanupTextures(); - llinfos << "Cleaning up pipeline" << llendl; - gPipeline.cleanup(); - stop_glerror(); - LLViewerTextureManager::cleanup() ; LLImageGL::cleanupClass() ; @@ -2163,13 +2165,19 @@ void LLViewerWindow::reshape(S32 width, S32 height) // tell the OS specific window code about min window size mWindow->setMinSize(min_window_width, min_window_height); + LLCoordScreen window_rect; + if (mWindow->getSize(&window_rect)) + { // Only save size if not maximized - gSavedSettings.setU32("WindowWidth", mWindowRectRaw.getWidth()); - gSavedSettings.setU32("WindowHeight", mWindowRectRaw.getHeight()); + gSavedSettings.setU32("WindowWidth", window_rect.mX); + gSavedSettings.setU32("WindowHeight", window_rect.mY); + } } LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height); + + LLLayoutStack::updateClass(); } } @@ -2373,7 +2381,7 @@ void LLViewerWindow::draw() gGL.matrixMode(LLRender::MM_MODELVIEW); LLUI::pushMatrix(); - LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f); + LLUI::translate( (F32) screen_x, (F32) screen_y); top_ctrl->draw(); LLUI::popMatrix(); } @@ -3181,12 +3189,6 @@ void LLViewerWindow::updateLayout() //gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible()); } - LLFloaterBuildOptions* build_options_floater = LLFloaterReg::findTypedInstance<LLFloaterBuildOptions>("build_options"); - if (build_options_floater && build_options_floater->getVisible()) - { - build_options_floater->updateGridMode(); - } - // Always update console if(gConsole) { @@ -4104,14 +4106,11 @@ void LLViewerWindow::resetSnapshotLoc() void LLViewerWindow::movieSize(S32 new_width, S32 new_height) { LLCoordWindow size; + LLCoordWindow new_size(new_width, new_height); gViewerWindow->getWindow()->getSize(&size); - if ( size.mX != new_width - || size.mY != new_height) + if ( size != new_size ) { - LLCoordWindow new_size(new_width, new_height); - LLCoordScreen screen_size; - gViewerWindow->getWindow()->convertCoords(new_size, &screen_size); - gViewerWindow->getWindow()->setSize(screen_size); + gViewerWindow->getWindow()->setSize(new_size); } } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bc7f5a9744..eada77156e 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -101,6 +101,8 @@ #include "llvoicevisualizer.h" // Ventrella #include "lldebugmessagebox.h" +#include "llsdutil.h" + extern F32 SPEED_ADJUST_MAX; extern F32 SPEED_ADJUST_MAX_SEC; extern F32 ANIM_SPEED_MAX; @@ -149,10 +151,6 @@ const F32 PELVIS_LAG_WALKING = 0.4f; // ...while walking const F32 PELVIS_LAG_MOUSELOOK = 0.15f; const F32 MOUSELOOK_PELVIS_FOLLOW_FACTOR = 0.5f; const F32 PELVIS_LAG_WHEN_FOLLOW_CAM_IS_ON = 0.0001f; // not zero! - something gets divided by this! - -const F32 PELVIS_ROT_THRESHOLD_SLOW = 60.0f; // amount of deviation allowed between -const F32 PELVIS_ROT_THRESHOLD_FAST = 2.0f; // the pelvis and the view direction - // when moving fast & slow const F32 TORSO_NOISE_AMOUNT = 1.0f; // Amount of deviation from up-axis, in degrees const F32 TORSO_NOISE_SPEED = 0.2f; // Time scale factor on torso noise. @@ -631,7 +629,6 @@ F32 LLVOAvatar::sLODFactor = 1.f; F32 LLVOAvatar::sPhysicsLODFactor = 1.f; BOOL LLVOAvatar::sUseImpostors = FALSE; BOOL LLVOAvatar::sJointDebug = FALSE; - F32 LLVOAvatar::sUnbakedTime = 0.f; F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; F32 LLVOAvatar::sGreyTime = 0.f; @@ -687,13 +684,16 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mNeedsSkin(FALSE), mLastSkinTime(0.f), mUpdatePeriod(1), + mFirstFullyVisible(TRUE), mFullyLoaded(FALSE), mPreviousFullyLoaded(FALSE), mFullyLoadedInitialized(FALSE), mSupportsAlphaLayers(FALSE), mLoadedCallbacksPaused(FALSE), mHasPelvisOffset( FALSE ), - mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")) + mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")), + mLastRezzedStatus(-1) + { LLMemType mt(LLMemType::MTYPE_AVATAR); //VTResume(); // VTune @@ -774,32 +774,46 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mLastPelvisFixup = 0.0f; } +std::string LLVOAvatar::avString() const +{ + std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); + return " Avatar '" + getFullname() + "' " + viz_string + " "; +} + +void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string comment) +{ + LL_INFOS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " Notification " << notification_name + << " : " << comment + << llendl; + + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); + args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + LLNotificationsUtil::add(notification_name,args); + } +} + //------------------------------------------------------------------------ // LLVOAvatar::~LLVOAvatar() //------------------------------------------------------------------------ LLVOAvatar::~LLVOAvatar() { - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + if (!mFullyLoaded) { - if (!mFullyLoaded) - { - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left after " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds as cloud." << llendl; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezLeftCloudNotification",args); - } - else - { - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left." << llendl; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezLeftNotification",args); - } - + debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); } + else + { + debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding"); + } + lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; mRoot.removeAllChildren(); @@ -848,6 +862,8 @@ LLVOAvatar::~LLVOAvatar() mAnimationSources.clear(); LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; + getPhases().clearPhases(); + lldebugs << "LLVOAvatar Destructor end" << llendl; } @@ -881,6 +897,55 @@ BOOL LLVOAvatar::isFullyBaked() return TRUE; } +BOOL LLVOAvatar::isFullyTextured() const +{ + for (S32 i = 0; i < mMeshLOD.size(); i++) + { + LLViewerJoint* joint = (LLViewerJoint*) mMeshLOD[i]; + if (i==MESH_ID_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) + { + continue; // don't care about skirt textures if we're not wearing one. + } + if (!joint) + { + continue; // nonexistent LOD OK. + } + std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin(); + if (meshIter != joint->mMeshParts.end()) + { + LLViewerJointMesh *mesh = (LLViewerJointMesh *) *meshIter; + if (!mesh) + { + continue; // nonexistent mesh OK + } + if (mesh->mTexture.notNull() && mesh->mTexture->hasGLTexture()) + { + continue; // Mesh exists and has a baked texture. + } + if (mesh->mLayerSet && mesh->mLayerSet->hasComposite()) + { + continue; // Mesh exists and has a composite texture. + } + // Fail + return FALSE; + } + } + return TRUE; +} + +BOOL LLVOAvatar::hasGray() const +{ + return !getIsCloud() && !isFullyTextured(); +} + +S32 LLVOAvatar::getRezzedStatus() const +{ + if (getIsCloud()) return 0; + if (isFullyTextured()) return 2; + llassert(hasGray()); + return 1; // gray +} + void LLVOAvatar::deleteLayerSetCaches(bool clearAll) { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) @@ -928,6 +993,31 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars) } // static +void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) +{ + counts.clear(); + counts.resize(3); + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + if (!inst) + continue; + S32 rez_status = inst->getRezzedStatus(); + counts[rez_status]++; + } +} + +// static +std::string LLVOAvatar::rezStatusToString(S32 rez_status) +{ + if (rez_status==0) return "cloud"; + if (rez_status==1) return "gray"; + if (rez_status==2) return "textured"; + return "unknown"; +} + +// static void LLVOAvatar::dumpBakedStatus() { LLVector3d camera_pos_global = gAgentCamera.getCameraPositionGlobal(); @@ -2252,18 +2342,12 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); // Print out arrival information once we have name of avatar. - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + if (has_name && getNVPair("FirstName")) { - if (has_name && getNVPair("FirstName")) - { - mDebugExistenceTimer.reset(); - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezArrivedNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' arrived." << llendl; - } + mDebugExistenceTimer.reset(); + debugAvatarRezTime("AvatarRezArrivedNotification","avatar arrived"); } + if(retval & LLViewerObject::INVALID_UPDATE) { if (isSelf()) @@ -2769,16 +2853,16 @@ void LLVOAvatar::idleUpdateLoadingEffect() // update visibility when avatar is partially loaded if (updateIsFullyLoaded()) // changed? { - if (isFullyLoaded() && isSelf()) + if (isFullyLoaded() && mFirstFullyVisible && isSelf()) { - static bool first_fully_visible = true; - if (first_fully_visible) - { - llinfos << "self isFullyLoaded, first_fully_visible" << llendl; - - first_fully_visible = false; - LLAppearanceMgr::instance().onFirstFullyVisible(); - } + LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL; + mFirstFullyVisible = FALSE; + LLAppearanceMgr::instance().onFirstFullyVisible(); + } + if (isFullyLoaded() && mFirstFullyVisible && !isSelf()) + { + LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL; + mFirstFullyVisible = FALSE; } if (isFullyLoaded()) { @@ -2922,43 +3006,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - BOOL new_name = FALSE; - if (visible_chat != mVisibleChat) + BOOL new_name = FALSE; + if (visible_chat != mVisibleChat) + { + mVisibleChat = visible_chat; + new_name = TRUE; + } + + if (sRenderGroupTitles != mRenderGroupTitles) + { + mRenderGroupTitles = sRenderGroupTitles; + new_name = TRUE; + } + + // First Calculate Alpha + // If alpha > 0, create mNameText if necessary, otherwise delete it + F32 alpha = 0.f; + if (mAppAngle > 5.f) + { + const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; + if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) { - mVisibleChat = visible_chat; - new_name = TRUE; + alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; } - - if (sRenderGroupTitles != mRenderGroupTitles) + else { - mRenderGroupTitles = sRenderGroupTitles; - new_name = TRUE; + // ...not fading, full alpha + alpha = 1.f; } - - // First Calculate Alpha - // If alpha > 0, create mNameText if necessary, otherwise delete it - F32 alpha = 0.f; - if (mAppAngle > 5.f) - { - const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) - { - alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; - } - else - { - // ...not fading, full alpha - alpha = 1.f; - } - } - else if (mAppAngle > 2.f) - { - // far away is faded out also - alpha = (mAppAngle-2.f)/3.f; - } + } + else if (mAppAngle > 2.f) + { + // far away is faded out also + alpha = (mAppAngle-2.f)/3.f; + } if (alpha <= 0.f) - { + { if (mNameText) { mNameText->markDead(); @@ -2968,19 +3052,19 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - if (!mNameText) - { + if (!mNameText) + { mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( - LLHUDObject::LL_HUD_NAME_TAG) ); + LLHUDObject::LL_HUD_NAME_TAG) ); //mNameText->setMass(10.f); - mNameText->setSourceObject(this); + mNameText->setSourceObject(this); mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); - mNameText->setVisibleOffScreen(TRUE); - mNameText->setMaxLines(11); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - sNumVisibleChatBubbles++; - new_name = TRUE; - } + mNameText->setVisibleOffScreen(TRUE); + mNameText->setMaxLines(11); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + sNumVisibleChatBubbles++; + new_name = TRUE; + } LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); mNameText->setPositionAgent(name_position); @@ -2989,10 +3073,10 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) - { - LLNameValue *title = getNVPair("Title"); - LLNameValue* firstname = getNVPair("FirstName"); - LLNameValue* lastname = getNVPair("LastName"); +{ + LLNameValue *title = getNVPair("Title"); + LLNameValue* firstname = getNVPair("FirstName"); + LLNameValue* lastname = getNVPair("LastName"); // Avatars must have a first and last name if (!firstname || !lastname) return; @@ -3006,34 +3090,23 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) is_muted = false; } else - { + { is_muted = LLMuteList::getInstance()->isMuted(getID()); } bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); bool is_cloud = getIsCloud(); - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - if (is_appearance != mNameAppearance) - { - if (is_appearance) - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; - } - else - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; - } - } - } + if (is_appearance != mNameAppearance) + { + if (is_appearance) + { + debugAvatarRezTime("AvatarRezEnteredAppearanceNotification","entered appearance mode"); + } + else + { + debugAvatarRezTime("AvatarRezLeftAppearanceNotification","left appearance mode"); + } + } // Rebuild name tag if state change detected if (mNameString.empty() @@ -3043,56 +3116,56 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) || is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute - || is_appearance != mNameAppearance + || is_appearance != mNameAppearance || is_friend != mNameFriend || is_cloud != mNameCloud) - { + { LLColor4 name_tag_color = getNameTagColor(is_friend); clearNameTag(); if (is_away || is_muted || is_busy || is_appearance) - { + { std::string line; - if (is_away) - { - line += LLTrans::getString("AvatarAway"); + if (is_away) + { + line += LLTrans::getString("AvatarAway"); line += ", "; - } - if (is_busy) - { + } + if (is_busy) + { line += LLTrans::getString("AvatarBusy"); line += ", "; } if (is_muted) - { + { line += LLTrans::getString("AvatarMuted"); - line += ", "; - } + line += ", "; + } if (is_appearance) { line += LLTrans::getString("AvatarEditingAppearance"); line += ", "; - } + } if (is_cloud) - { + { line += LLTrans::getString("LoadingData"); line += ", "; } // trim last ", " line.resize( line.length() - 2 ); addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); + LLFontGL::getFontSansSerifSmall()); } if (sRenderGroupTitles && title && title->getString() && title->getString()[0] != '\0') - { + { std::string title_str = title->getString(); LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); - } + LLFontGL::getFontSansSerifSmall()); + } static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); @@ -3105,120 +3178,120 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) // ...call this function back when the name arrives // and force a rebuild LLAvatarNameCache::get(getID(), - boost::bind(&LLVOAvatar::clearNameTag, this)); - } + boost::bind(&LLVOAvatar::clearNameTag, this)); + } // Might be blank if name not available yet, that's OK if (show_display_names) { addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerif()); - } + LLFontGL::getFontSansSerif()); + } // Suppress SLID display if display name matches exactly (ugh) if (show_usernames && !av_name.mIsDisplayNameDefault) - { + { // *HACK: Desaturate the color LLColor4 username_color = name_tag_color * 0.83f; addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); + LLFontGL::getFontSansSerifSmall()); } - } + } else - { + { const LLFontGL* font = LLFontGL::getFontSansSerif(); std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); - } + } - mNameAway = is_away; - mNameBusy = is_busy; - mNameMute = is_muted; - mNameAppearance = is_appearance; + mNameAway = is_away; + mNameBusy = is_busy; + mNameMute = is_muted; + mNameAppearance = is_appearance; mNameFriend = is_friend; - mNameCloud = is_cloud; - mTitle = title ? title->getString() : ""; - LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); - new_name = TRUE; - } + mNameCloud = is_cloud; + mTitle = title ? title->getString() : ""; + LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); + new_name = TRUE; + } if (mVisibleChat) - { - mNameText->setFont(LLFontGL::getFontSansSerif()); + { + mNameText->setFont(LLFontGL::getFontSansSerif()); mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - char line[MAX_STRING]; /* Flawfinder: ignore */ - line[0] = '\0'; - std::deque<LLChat>::iterator chat_iter = mChats.begin(); - mNameText->clearString(); - - LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); - LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); - LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); - if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) - { - ++chat_iter; - } - - for(; chat_iter != mChats.end(); ++chat_iter) - { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); - LLFontGL::StyleFlags style; - switch(chat_iter->mChatType) - { - case CHAT_TYPE_WHISPER: - style = LLFontGL::ITALIC; - break; - case CHAT_TYPE_SHOUT: - style = LLFontGL::BOLD; - break; - default: - style = LLFontGL::NORMAL; - break; - } - if (chat_fade_amt < 1.f) - { - F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); - } - else if (chat_fade_amt < 2.f) - { - F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); - } - else if (chat_fade_amt < 3.f) - { - // *NOTE: only remove lines down to minimum number - mNameText->addLine(chat_iter->mText, old_chat, style); - } - } - mNameText->setVisibleOffScreen(TRUE); + char line[MAX_STRING]; /* Flawfinder: ignore */ + line[0] = '\0'; + std::deque<LLChat>::iterator chat_iter = mChats.begin(); + mNameText->clearString(); - if (mTyping) - { - S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; - switch(dot_count) - { - case 1: - mNameText->addLine(".", new_chat); - break; - case 2: - mNameText->addLine("..", new_chat); - break; - case 3: - mNameText->addLine("...", new_chat); - break; - } + LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); + LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); + LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); + if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) + { + ++chat_iter; + } - } + for(; chat_iter != mChats.end(); ++chat_iter) + { + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + LLFontGL::StyleFlags style; + switch(chat_iter->mChatType) + { + case CHAT_TYPE_WHISPER: + style = LLFontGL::ITALIC; + break; + case CHAT_TYPE_SHOUT: + style = LLFontGL::BOLD; + break; + default: + style = LLFontGL::NORMAL; + break; } - else + if (chat_fade_amt < 1.f) + { + F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); + } + else if (chat_fade_amt < 2.f) { + F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); + } + else if (chat_fade_amt < 3.f) + { + // *NOTE: only remove lines down to minimum number + mNameText->addLine(chat_iter->mText, old_chat, style); + } + } + mNameText->setVisibleOffScreen(TRUE); + + if (mTyping) + { + S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; + switch(dot_count) + { + case 1: + mNameText->addLine(".", new_chat); + break; + case 2: + mNameText->addLine("..", new_chat); + break; + case 3: + mNameText->addLine("...", new_chat); + break; + } + + } + } + else + { // ...not using chat bubbles, just names mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setVisibleOffScreen(FALSE); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + mNameText->setVisibleOffScreen(FALSE); } } @@ -3241,8 +3314,8 @@ void LLVOAvatar::clearNameTag() { mNameString.clear(); if (mNameText) - { - mNameText->setLabel(""); + { + mNameText->setLabel(""); mNameText->setString( "" ); } } @@ -3365,7 +3438,7 @@ void LLVOAvatar::slamPosition() mRoot.updateWorldMatrixChildren(); } -bool LLVOAvatar::isVisuallyMuted() +bool LLVOAvatar::isVisuallyMuted() const { static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); @@ -3434,7 +3507,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // the rest should only be done occasionally for far away avatars //-------------------------------------------------------------------- - if (visible && !isSelf() && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) + if (visible && (!isSelf() || isVisuallyMuted()) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) { const LLVector4a* ext = mDrawable->getSpatialExtents(); LLVector4a size; @@ -3474,6 +3547,11 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE; } + else + { + mUpdatePeriod = 1; + } + // don't early out for your own avatar, as we rely on your animations playing reliably // for example, the "turn around" animation when entering customize avatar needs to trigger @@ -3652,7 +3730,11 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook(); LLVector3 pelvisDir( mRoot.getWorldMatrix().getFwdRow4().mV ); - F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, PELVIS_ROT_THRESHOLD_SLOW, PELVIS_ROT_THRESHOLD_FAST); + + static LLCachedControl<F32> s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow"); + static LLCachedControl<F32> s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast"); + + F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, s_pelvis_rot_threshold_slow, s_pelvis_rot_threshold_fast); if (self_in_mouselook) { @@ -3959,7 +4041,7 @@ void LLVOAvatar::updateVisibility() LLNameValue* firstname = getNVPair("FirstName"); if (firstname) { - llinfos << "Avatar " << firstname->getString() << " updating visiblity" << llendl; + LL_DEBUGS("Avatar") << avString() << " updating visibility" << LL_ENDL; } else { @@ -4125,11 +4207,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { //LOD changed or new mesh created, allocate new vertex buffer if needed if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) { - updateMeshData(); + updateMeshData(); mDirtyMesh = 0; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } } if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -4171,7 +4253,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) LLNameValue* firstname = getNVPair("FirstName"); if (firstname) { - llinfos << "Avatar " << firstname->getString() << " in render" << llendl; + LL_DEBUGS("Avatar") << avString() << " in render" << LL_ENDL; } else { @@ -5029,7 +5111,7 @@ void LLVOAvatar::addDebugText(const std::string& text) //----------------------------------------------------------------------------- // getID() //----------------------------------------------------------------------------- -const LLUUID& LLVOAvatar::getID() +const LLUUID& LLVOAvatar::getID() const { return mID; } @@ -6388,10 +6470,10 @@ BOOL LLVOAvatar::isVisible() const } // Determine if we have enough avatar data to render -BOOL LLVOAvatar::getIsCloud() +BOOL LLVOAvatar::getIsCloud() const { // Do we have a shape? - if (visualParamWeightsAreDefault()) + if ((const_cast<LLVOAvatar*>(this))->visualParamWeightsAreDefault()) { return TRUE; } @@ -6410,11 +6492,53 @@ BOOL LLVOAvatar::getIsCloud() return FALSE; } +void LLVOAvatar::updateRezzedStatusTimers() +{ + // State machine for rezzed status. Statuses are 0 = cloud, 1 = gray, 2 = textured. + // Purpose is to collect time data for each period of cloud or cloud+gray. + S32 rez_status = getRezzedStatus(); + if (rez_status != mLastRezzedStatus) + { + LL_DEBUGS("Avatar") << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << LL_ENDL; + bool is_cloud_or_gray = (rez_status==0 || rez_status==1); + bool was_cloud_or_gray = (mLastRezzedStatus==0 || mLastRezzedStatus==1); + bool is_cloud = (rez_status==0); + bool was_cloud = (mLastRezzedStatus==0); + + // Non-cloud to cloud + if (is_cloud && !was_cloud) + { + // start cloud timer. + getPhases().startPhase("cloud"); + } + else if (was_cloud && !is_cloud) + { + // stop cloud timer, which will capture stats. + getPhases().stopPhase("cloud"); + } + + // Non-cloud-or-gray to cloud-or-gray + if (is_cloud_or_gray && !was_cloud_or_gray) + { + // start cloud-or-gray timer. + getPhases().startPhase("cloud-or-gray"); + } + else if (was_cloud_or_gray && !is_cloud_or_gray) + { + // stop cloud-or-gray timer, which will capture stats. + getPhases().stopPhase("cloud-or-gray"); + } + + mLastRezzedStatus = rez_status; + } +} + // call periodically to keep isFullyLoaded up to date. // returns true if the value has changed. BOOL LLVOAvatar::updateIsFullyLoaded() { const BOOL loading = getIsCloud(); + updateRezzedStatusTimers(); updateRuthTimer(loading); return processFullyLoadedChange(loading); } @@ -6429,27 +6553,19 @@ void LLVOAvatar::updateRuthTimer(bool loading) if (mPreviousFullyLoaded) { mRuthTimer.reset(); - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' became cloud." << llendl; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezCloudNotification",args); - } - mRuthDebugTimer.reset(); + debugAvatarRezTime("AvatarRezCloudNotification","became cloud"); } const F32 LOADING_TIMEOUT__SECONDS = 120.f; if (mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT__SECONDS) { - llinfos << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' " + LL_DEBUGS("Avatar") << avString() + << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' " << "( Params loaded : " << !visualParamWeightsAreDefault() << " ) " << "( Lower : " << isTextureDefined(TEX_LOWER_BAKED) << " ) " << "( Upper : " << isTextureDefined(TEX_UPPER_BAKED) << " ) " << "( Head : " << isTextureDefined(TEX_HEAD_BAKED) << " )." - << llendl; + << LL_ENDL; LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); mRuthTimer.reset(); @@ -6466,20 +6582,13 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + if (!mPreviousFullyLoaded && !loading && mFullyLoaded) { - if (!mPreviousFullyLoaded && !loading && mFullyLoaded) - { - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' resolved in " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds." << llendl; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezNotification",args); - } + debugAvatarRezTime("AvatarRezNotification","fully loaded"); } // did our loading state "change" from last call? + // runway - why are we updating every 30 calls even if nothing has changed? const S32 UPDATE_RATE = 30; BOOL changed = ((mFullyLoaded != mPreviousFullyLoaded) || // if the value is different from the previous call @@ -6919,7 +7028,7 @@ LLColor4 LLVOAvatar::getDummyColor() void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { - llinfos << (isSelf() ? "Self: " : "Other: ") << context << llendl; + LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); ++iter) @@ -6929,23 +7038,23 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const const LLViewerTexture* te_image = getImage(iter->first,0); if( !te_image ) { - llinfos << " " << texture_dict->mName << ": null ptr" << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": null ptr" << LL_ENDL; } else if( te_image->getID().isNull() ) { - llinfos << " " << texture_dict->mName << ": null UUID" << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": null UUID" << LL_ENDL; } else if( te_image->getID() == IMG_DEFAULT ) { - llinfos << " " << texture_dict->mName << ": IMG_DEFAULT" << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": IMG_DEFAULT" << LL_ENDL; } else if( te_image->getID() == IMG_DEFAULT_AVATAR ) { - llinfos << " " << texture_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": IMG_DEFAULT_AVATAR" << LL_ENDL; } else { - llinfos << " " << texture_dict->mName << ": " << te_image->getID() << llendl; + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": " << te_image->getID() << LL_ENDL; } } } @@ -7076,6 +7185,7 @@ void LLVOAvatar::rebuildHUD() //----------------------------------------------------------------------------- void LLVOAvatar::onFirstTEMessageReceived() { + LL_INFOS("Avatar") << avString() << LL_ENDL; if( !mFirstTEMessageReceived ) { mFirstTEMessageReceived = TRUE; @@ -7104,6 +7214,7 @@ void LLVOAvatar::onFirstTEMessageReceived() image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), src_callback_list, paused); } + LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL; image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); } @@ -7162,14 +7273,16 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) LLMemType mt(LLMemType::MTYPE_AVATAR); -// llinfos << "processAvatarAppearance start " << mID << llendl; BOOL is_first_appearance_message = !mFirstAppearanceMessageReceived; - mFirstAppearanceMessageReceived = TRUE; + LL_INFOS("Avatar") << avString() << "processAvatarAppearance start " << mID + << " first? " << is_first_appearance_message << " self? " << isSelf() << LL_ENDL; + + if( isSelf() ) { - llwarns << "Received AvatarAppearance for self" << llendl; + llwarns << avString() << "Received AvatarAppearance for self" << llendl; if( mFirstTEMessageReceived ) { // llinfos << "processAvatarAppearance end " << mID << llendl; @@ -7197,7 +7310,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } - if( !is_first_appearance_message ) + // runway - was + // if (!is_first_appearance_message ) + // which means it would be called on second appearance message - probably wrong. + if (is_first_appearance_message ) { onFirstTEMessageReceived(); } @@ -7218,6 +7334,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing if( num_blocks > 1 && !drop_visual_params_debug) { + LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; BOOL params_changed = FALSE; BOOL interp_params = FALSE; @@ -7290,6 +7407,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) else { // AvatarAppearance message arrived without visual params + LL_DEBUGS("Avatar") << avString() << "no visual params" << LL_ENDL; if (drop_visual_params_debug) { llinfos << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << llendl; @@ -7442,8 +7560,15 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture // static void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { + + LLUUID *avatar_idp = (LLUUID *)userdata; LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); + + if (selfp) + { + LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << LL_ENDL; + } if (!success && selfp) { @@ -7455,13 +7580,20 @@ void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTextu } } -void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +// Static +void LLVOAvatar::onBakedTextureLoaded(BOOL success, + LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, + S32 discard_level, BOOL final, void* userdata) { //llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl; LLUUID id = src_vi->getID(); LLUUID *avatar_idp = (LLUUID *)userdata; LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); + if (selfp) + { + LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << " id " << src_vi->getID() << LL_ENDL; + } if (selfp && !success) { @@ -7483,6 +7615,8 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_ // Called when baked texture is loaded and also when we start up with a baked texture void LLVOAvatar::useBakedTexture( const LLUUID& id ) { + + /* if(id == head_baked->getID()) mHeadBakedLoaded = TRUE; mLastHeadBakedID = id; @@ -7493,6 +7627,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); if (id == image_baked->getID()) { + LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; mBakedTextureDatas[i].mIsLoaded = true; mBakedTextureDatas[i].mLastTextureIndex = id; mBakedTextureDatas[i].mIsUsed = true; @@ -7532,12 +7667,16 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) void LLVOAvatar::dumpArchetypeXML( void* ) { LLAPRFile outfile; - outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB ); - apr_file_t* file = outfile.getFileHandle() ; + outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"new archetype.xml"), LL_APR_WB ); + apr_file_t* file = outfile.getFileHandle(); if (!file) { return; } + else + { + llinfos << "xmlfile write handle obtained : " << gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"new archetype.xml") << llendl; + } apr_file_printf( file, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n" ); apr_file_printf( file, "<linden_genepool version=\"1.0\">\n" ); @@ -7577,6 +7716,11 @@ void LLVOAvatar::dumpArchetypeXML( void* ) } apr_file_printf( file, "\t</archetype>\n" ); apr_file_printf( file, "\n</linden_genepool>\n" ); + //explictly close the file if it is still open which it should be + if (file) + { + outfile.close(); + } } @@ -7658,6 +7802,9 @@ void LLVOAvatar::cullAvatarsByPixelArea() } } + // runway - this doesn't detect gray/grey state. + // think we just need to be checking self av since it's the only + // one with lltexlayer stuff. S32 grey_avatars = 0; if (LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) { @@ -8296,7 +8443,7 @@ void LLVOAvatar::updateImpostors() BOOL LLVOAvatar::isImpostor() const { - return (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD) ? TRUE : FALSE; + return (isVisuallyMuted() || (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE; } @@ -8461,7 +8608,9 @@ void LLVOAvatar::idleUpdateRenderCost() } } - setDebugText(llformat("%d", cost)); + + std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); + setDebugText(llformat("%s %d", viz_string.c_str(), cost)); mVisualComplexity = cost; F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index dd0317f555..6fb56a4c0b 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -48,6 +48,7 @@ #include "lltexglobalcolor.h" #include "lldriverparam.h" #include "material_codes.h" // LL_MCODE_END +#include "llviewerstats.h" extern const LLUUID ANIM_AGENT_BODY_NOISE; extern const LLUUID ANIM_AGENT_BREATHE_ROT; @@ -185,7 +186,7 @@ public: void resetSpecificJointPosition( const std::string& name ); virtual const char* getAnimationPrefix() { return "avatar"; } - virtual const LLUUID& getID(); + virtual const LLUUID& getID() const; virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); virtual LLJoint* findCollisionVolume(U32 volume_id); virtual S32 getCollisionVolumeID(std::string &name); @@ -277,14 +278,27 @@ public: public: BOOL isFullyLoaded() const; bool isTooComplex() const; - bool visualParamWeightsAreDefault(); + bool visualParamWeightsAreDefault(); + virtual BOOL getIsCloud() const; + BOOL isFullyTextured() const; + BOOL hasGray() const; + S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured. + void updateRezzedStatusTimers(); + + S32 mLastRezzedStatus; + + LLViewerStats::PhaseMap& getPhases() + { + return mPhases; + } + protected: - virtual BOOL getIsCloud(); BOOL updateIsFullyLoaded(); BOOL processFullyLoadedChange(bool loading); void updateRuthTimer(bool loading); F32 calcMorphAmount(); private: + BOOL mFirstFullyVisible; BOOL mFullyLoaded; BOOL mPreviousFullyLoaded; BOOL mFullyLoadedInitialized; @@ -292,6 +306,28 @@ private: S32 mVisualComplexity; LLFrameTimer mFullyLoadedTimer; LLFrameTimer mRuthTimer; + +public: + class ScopedPhaseSetter + { + public: + ScopedPhaseSetter(LLVOAvatar *avatarp, std::string phase_name): + mAvatar(avatarp), mPhaseName(phase_name) + { + if (mAvatar) { mAvatar->getPhases().startPhase(mPhaseName); } + } + ~ScopedPhaseSetter() + { + if (mAvatar) { mAvatar->getPhases().stopPhase(mPhaseName); } + } + private: + std::string mPhaseName; + LLVOAvatar* mAvatar; + }; + +private: + LLViewerStats::PhaseMap mPhases; + protected: LLFrameTimer mInvisibleTimer; @@ -382,7 +418,7 @@ private: public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); - bool isVisuallyMuted(); + bool isVisuallyMuted() const; U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); @@ -518,9 +554,10 @@ public: virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; -protected: BOOL isFullyBaked(); static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); + static void getNearbyRezzedStats(std::vector<S32>& counts); + static std::string rezStatusToString(S32 status); //-------------------------------------------------------------------- // Baked textures @@ -882,6 +919,7 @@ private: public: std::string getFullname() const; // Returns "FirstName LastName" + std::string avString() const; // Frequently used string in log messages "Avatar '<full name'" protected: static void getAnimLabels(LLDynamicArray<std::string>* labels); static void getAnimNames(LLDynamicArray<std::string>* names); @@ -983,7 +1021,9 @@ private: // Avatar Rez Metrics //-------------------------------------------------------------------- public: + void debugAvatarRezTime(std::string notification_name, std::string comment = ""); F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } + protected: LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index f1df67494f..d2609e5587 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -58,6 +58,8 @@ #include "llappearancemgr.h" #include "llmeshrepository.h" #include "llvovolume.h" +#include "llsdutil.h" +#include "llstartup.h" #if LL_MSVC // disable boost::lexical_cast warning @@ -66,14 +68,48 @@ #include <boost/lexical_cast.hpp> -LLVOAvatarSelf *gAgentAvatarp = NULL; +LLPointer<LLVOAvatarSelf> gAgentAvatarp = NULL; + BOOL isAgentAvatarValid() { - return (gAgentAvatarp && + return (gAgentAvatarp.notNull() && (gAgentAvatarp->getRegion() != NULL) && (!gAgentAvatarp->isDead())); } +void selfStartPhase(const std::string& phase_name) +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->getPhases().startPhase(phase_name); + } +} + +void selfStopPhase(const std::string& phase_name) +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->getPhases().stopPhase(phase_name); + } +} + +void selfClearPhases() +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->getPhases().clearPhases(); + gAgentAvatarp->mLastRezzedStatus = -1; + } +} + +void selfStopAllPhases() +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->getPhases().stopAllPhases(); + } +} + using namespace LLVOAvatarDefines; /********************************************************************************* @@ -130,7 +166,8 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, LLVOAvatar(id, pcode, regionp), mScreenp(NULL), mLastRegionHandle(0), - mRegionCrossingCount(0) + mRegionCrossingCount(0), + mInitialBakesLoaded(false) { gAgentWearables.setAvatarObject(this); @@ -163,6 +200,7 @@ void LLVOAvatarSelf::initInstance() { mDebugBakedTextureTimes[i][0] = -1.0f; mDebugBakedTextureTimes[i][1] = -1.0f; + mInitialBakeIDs[i] = LLUUID::null; } status &= buildMenus(); @@ -365,9 +403,9 @@ BOOL LLVOAvatarSelf::buildMenus() item_params.label = sub_piemenu_name; } item_params.name =(item_params.label ); - item_params.on_click.function_name = "Attachment.Detach"; + item_params.on_click.function_name = "Attachment.DetachFromPoint"; item_params.on_click.parameter = iter->first; - item_params.on_enable.function_name = "Attachment.EnableDetach"; + item_params.on_enable.function_name = "Attachment.PointFilled"; item_params.on_enable.parameter = iter->first; LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); @@ -761,6 +799,41 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id) } } +//virtual +U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp) +{ + U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp); + + if (mInitialBakesLoaded == false && retval == 0x0) + { + // call update textures to force the images to be created + updateMeshTextures(); + + // unpack the texture UUIDs to the texture slots + retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + + // need to trigger a few operations to get the avatar to use the new bakes + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const LLVOAvatarDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex; + LLUUID texture_id = getTEImage(te)->getID(); + setNewBakedTexture(te, texture_id); + mInitialBakeIDs[i] = texture_id; + } + + onFirstTEMessageReceived(); + + mInitialBakesLoaded = true; + } + + return retval; +} + + void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index) { if (te >= TEX_NUM_INDICES) @@ -1888,7 +1961,7 @@ void LLVOAvatarSelf::dumpTotalLocalTextureByteCount() llinfos << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << llendl; } -BOOL LLVOAvatarSelf::getIsCloud() +BOOL LLVOAvatarSelf::getIsCloud() const { // do we have our body parts? if (gAgentWearables.getWearableCount(LLWearableType::WT_SHAPE) == 0 || @@ -2054,6 +2127,80 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const return text; } +// Dump avatar metrics data. +LLSD LLVOAvatarSelf::metricsData() +{ + // runway - add region info + LLSD result; + result["id"] = getID(); + result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus()); + result["is_self"] = isSelf(); + std::vector<S32> rez_counts; + LLVOAvatar::getNearbyRezzedStats(rez_counts); + result["nearby"] = LLSD::emptyMap(); + for (S32 i=0; i<rez_counts.size(); ++i) + { + std::string rez_status_name = LLVOAvatar::rezStatusToString(i); + result["nearby"][rez_status_name] = rez_counts[i]; + } + result["timers"]["debug_existence"] = mDebugExistenceTimer.getElapsedTimeF32(); + result["timers"]["ruth_debug"] = mRuthDebugTimer.getElapsedTimeF32(); + result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32(); + result["timers"]["invisible"] = mInvisibleTimer.getElapsedTimeF32(); + result["timers"]["fully_loaded"] = mFullyLoadedTimer.getElapsedTimeF32(); + result["phases"] = getPhases().dumpPhases(); + result["startup"] = LLStartUp::getPhases().dumpPhases(); + + return result; +} + +class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder +{ +public: + ViewerAppearanceChangeMetricsResponder() + { + } + + virtual void completed(U32 status, + const std::string& reason, + const LLSD& content) + { + if (isGoodStatus(status)) + { + LL_DEBUGS("Avatar") << "OK" << LL_ENDL; + result(content); + } + else + { + LL_WARNS("Avatar") << "Failed " << status << " reason " << reason << LL_ENDL; + error(status,reason); + } + } +}; + +void LLVOAvatarSelf::sendAppearanceChangeMetrics() +{ + // gAgentAvatarp->stopAllPhases(); + + LLSD msg = metricsData(); + msg["message"] = "ViewerAppearanceChangeMetrics"; + + LL_DEBUGS("Avatar") << avString() << "message: " << ll_pretty_print_sd(msg) << LL_ENDL; + std::string caps_url; + if (getRegion()) + { + // runway - change here to activate. + caps_url = getRegion()->getCapability("ViewerMetrics"); + } + if (!caps_url.empty()) + { + LLCurlRequest::headers_t headers; + LLHTTPClient::post(caps_url, + msg, + new ViewerAppearanceChangeMetricsResponder); + } +} + const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const { if (canGrabBakedTexture(baked_index)) @@ -2252,11 +2399,25 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) if (isAllLocalTextureDataFinal()) { LLNotificationsUtil::add("AvatarRezSelfBakedDoneNotification",args); + LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32() + << " Notification " << "AvatarRezSelfBakedDoneNotification" + << llendl; } else { args["STATUS"] = debugDumpAllLocalTextureDataInfo(); LLNotificationsUtil::add("AvatarRezSelfBakedUpdateNotification",args); + LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32() + << " Notification " << "AvatarRezSelfBakedUpdateNotification" + << llendl; } } @@ -2264,7 +2425,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) } } -// FIXME: This is never called. Something may be broken. +// FIXME: This is not called consistently. Something may be broken. void LLVOAvatarSelf::outputRezDiagnostics() const { if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) @@ -2273,11 +2434,11 @@ void LLVOAvatarSelf::outputRezDiagnostics() const } const F32 final_time = mDebugSelfLoadTimer.getElapsedTimeF32(); - llinfos << "REZTIME: Myself rez stats:" << llendl; - llinfos << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl; - llinfos << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl; - llinfos << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; - llinfos << "\t Load time for each texture: " << llendl; + LL_DEBUGS("Avatar") << "REZTIME: Myself rez stats:" << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; + LL_DEBUGS("Avatar") << "\t Load time for each texture: " << llendl; for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) { std::stringstream out; @@ -2301,12 +2462,14 @@ void LLVOAvatarSelf::outputRezDiagnostics() const // Don't print out non-existent textures. if (j != 0) - llinfos << out.str() << llendl; + { + LL_DEBUGS("Avatar") << out.str() << LL_ENDL; + } } - llinfos << "\t Time points for each upload (start / finish)" << llendl; + LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << llendl; for (U32 i = 0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) { - llinfos << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl; + LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl; } for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); @@ -2318,15 +2481,16 @@ void LLVOAvatarSelf::outputRezDiagnostics() const if (!layerset) continue; const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); if (!layerset_buffer) continue; - llinfos << layerset_buffer->dumpTextureInfo() << llendl; + LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl; } } void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const { - LL_DEBUGS("Avatar Rez") + LL_INFOS("Avatar") + << avString() << llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) - << llendl; + << LL_ENDL; } void LLVOAvatarSelf::reportAvatarRezTime() const @@ -2350,6 +2514,18 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid { if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet) { + if (mInitialBakeIDs[i] != LLUUID::null) + { + if (mInitialBakeIDs[i] == uuid) + { + llinfos << "baked texture correctly loaded at login! " << i << llendl; + } + else + { + llwarns << "baked texture does not match id loaded at login!" << i << llendl; + } + mInitialBakeIDs[i] = LLUUID::null; + } mBakedTextureDatas[i].mTexLayerSet->cancelUpload(); } } @@ -2477,6 +2653,20 @@ LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const return NULL; } +LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const +{ + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + if (baked_index >= 0 && baked_index < BAKED_NUM_INDICES) + { + return mBakedTextureDatas[baked_index].mTexLayerSet; + } + return NULL; +} + + // static void LLVOAvatarSelf::onCustomizeStart() { @@ -2557,49 +2747,6 @@ BOOL LLVOAvatarSelf::needsRenderBeam() // static void LLVOAvatarSelf::deleteScratchTextures() { - if(gAuditTexture) - { - S32 total_tex_size = sScratchTexBytes ; - S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; - - if( sScratchTexNames.checkData( GL_LUMINANCE ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( GL_ALPHA ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( GL_COLOR_INDEX ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( LLRender::sGLCoreProfile ? GL_RG : GL_LUMINANCE_ALPHA ) ) - { - LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 2 * tex_size ; - } - if( sScratchTexNames.checkData( GL_RGB ) ) - { - LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 3 * tex_size ; - } - if( sScratchTexNames.checkData( GL_RGBA ) ) - { - LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 4 * tex_size ; - } - //others - while(total_tex_size > 0) - { - LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 4 * tex_size ; - } - } - for( LLGLuint* namep = sScratchTexNames.getFirstData(); namep; namep = sScratchTexNames.getNextData() ) diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 54dbe81993..543891ca63 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -93,15 +93,27 @@ public: /*virtual*/ void updateVisualParams(); /*virtual*/ void idleUpdateAppearanceAnimation(); + /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp); + private: // helper function. Passed in param is assumed to be in avatar's parameter list. BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE ); + /** Initialization ** ** *******************************************************************************/ +private: + LLUUID mInitialBakeIDs[6]; + bool mInitialBakesLoaded; + + /******************************************************************************** ** ** ** STATE @@ -121,7 +133,7 @@ public: // Loading state //-------------------------------------------------------------------- public: - /*virtual*/ BOOL getIsCloud(); + /*virtual*/ BOOL getIsCloud() const; //-------------------------------------------------------------------- // Region state @@ -229,6 +241,7 @@ public: void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i); void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; + LLTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; //-------------------------------------------------------------------- // Composites @@ -369,6 +382,8 @@ public: const LLTexLayerSet* debugGetLayerSet(LLVOAvatarDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } const std::string debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD + LLSD metricsData(); + void sendAppearanceChangeMetrics(); // send data associated with completing a change. private: LLFrameTimer mDebugSelfLoadTimer; F32 mDebugTimeWearablesLoaded; @@ -383,8 +398,13 @@ private: }; -extern LLVOAvatarSelf *gAgentAvatarp; +extern LLPointer<LLVOAvatarSelf> gAgentAvatarp; BOOL isAgentAvatarValid(); +void selfStartPhase(const std::string& phase_name); +void selfStopPhase(const std::string& phase_name); +void selfStopAllPhases(); +void selfClearPhases(); + #endif // LL_VO_AVATARSELF_H diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index df1d3f2955..820d1d73e1 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -27,8 +27,6 @@ #include "llviewerprecompiledheaders.h" #include "llvoicevivox.h" -#include <boost/tokenizer.hpp> - #include "llsdutil.h" // Linden library includes @@ -47,6 +45,7 @@ #include "llbase64.h" #include "llviewercontrol.h" #include "llappviewer.h" // for gDisconnected, gDisableVoice +#include "llprocess.h" // Viewer includes #include "llmutelist.h" // to check for muted avatars @@ -242,59 +241,21 @@ void LLVivoxVoiceClientCapResponder::result(const LLSD& content) } } - - -#if LL_WINDOWS -static HANDLE sGatewayHandle = 0; +static LLProcessPtr sGatewayPtr; static bool isGatewayRunning() { - bool result = false; - if(sGatewayHandle != 0) - { - DWORD waitresult = WaitForSingleObject(sGatewayHandle, 0); - if(waitresult != WAIT_OBJECT_0) - { - result = true; - } - } - return result; -} -static void killGateway() -{ - if(sGatewayHandle != 0) - { - TerminateProcess(sGatewayHandle,0); - } -} - -#else // Mac and linux - -static pid_t sGatewayPID = 0; -static bool isGatewayRunning() -{ - bool result = false; - if(sGatewayPID != 0) - { - // A kill with signal number 0 has no effect, just does error checking. It should return an error if the process no longer exists. - if(kill(sGatewayPID, 0) == 0) - { - result = true; - } - } - return result; + return sGatewayPtr && sGatewayPtr->isRunning(); } static void killGateway() { - if(sGatewayPID != 0) + if (sGatewayPtr) { - kill(sGatewayPID, SIGTERM); + sGatewayPtr->kill(); } } -#endif - /////////////////////////////////////////////////////////////////////////////////////////////// LLVivoxVoiceClient::LLVivoxVoiceClient() : @@ -790,7 +751,7 @@ void LLVivoxVoiceClient::stateMachine() } else if(!isGatewayRunning()) { - if(true) + if (true) // production build, not test { // Launch the voice daemon @@ -809,102 +770,33 @@ void LLVivoxVoiceClient::stateMachine() #endif // See if the vivox executable exists llstat s; - if(!LLFile::stat(exe_path, &s)) + if (!LLFile::stat(exe_path, &s)) { // vivox executable exists. Build the command line and launch the daemon. + LLProcess::Params params; + params.executable = exe_path; // SLIM SDK: these arguments are no longer necessary. // std::string args = " -p tcp -h -c"; - std::string args; - std::string cmd; std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); - if(loglevel.empty()) { loglevel = "-1"; // turn logging off completely } - - args += " -ll "; - args += loglevel; - - LL_DEBUGS("Voice") << "Args for SLVoice: " << args << LL_ENDL; - -#if LL_WINDOWS - PROCESS_INFORMATION pinfo; - STARTUPINFOA sinfo; - - memset(&sinfo, 0, sizeof(sinfo)); - - std::string exe_dir = gDirUtilp->getAppRODataDir(); - cmd = "SLVoice.exe"; - cmd += args; - - // So retarded. Windows requires that the second parameter to CreateProcessA be writable (non-const) string... - char *args2 = new char[args.size() + 1]; - strcpy(args2, args.c_str()); - if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo)) - { -// DWORD dwErr = GetLastError(); - } - else - { - // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on - // CloseHandle(pinfo.hProcess); // stops leaks - nothing else - sGatewayHandle = pinfo.hProcess; - CloseHandle(pinfo.hThread); // stops leaks - nothing else - } - - delete[] args2; -#else // LL_WINDOWS - // This should be the same for mac and linux - { - std::vector<std::string> arglist; - arglist.push_back(exe_path); - - // Split the argument string into separate strings for each argument - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep(" "); - tokenizer tokens(args, sep); - tokenizer::iterator token_iter; - for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) - { - arglist.push_back(*token_iter); - } - - // create an argv vector for the child process - char **fakeargv = new char*[arglist.size() + 1]; - int i; - for(i=0; i < arglist.size(); i++) - fakeargv[i] = const_cast<char*>(arglist[i].c_str()); + params.args.add("-ll"); + params.args.add(loglevel); + params.cwd = gDirUtilp->getAppRODataDir(); + sGatewayPtr = LLProcess::create(params); - fakeargv[i] = NULL; - - fflush(NULL); // flush all buffers before the child inherits them - pid_t id = vfork(); - if(id == 0) - { - // child - execv(exe_path.c_str(), fakeargv); - - // If we reach this point, the exec failed. - // Use _exit() instead of exit() per the vfork man page. - _exit(0); - } - - // parent - delete[] fakeargv; - sGatewayPID = id; - } -#endif // LL_WINDOWS mDaemonHost = LLHost(gSavedSettings.getString("VivoxVoiceHost").c_str(), gSavedSettings.getU32("VivoxVoicePort")); - } + } else { LL_INFOS("Voice") << exe_path << " not found." << LL_ENDL; - } + } } else - { + { // SLIM SDK: port changed from 44124 to 44125. // We can connect to a client gateway running on another host. This is useful for testing. // To do this, launch the gateway on a nearby host like this: diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index e9db37821b..312034022e 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -342,7 +342,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) blue_density = LLColor3(); blue_horizon = LLColor3(); haze_density = 0.f; - haze_horizon = LLColor3(); + haze_horizon = 1.f; density_multiplier = 0.f; max_y = 0.f; glow = LLColor3(); @@ -651,17 +651,17 @@ void LLVOSky::initAtmospherics(void) sunlight_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("sunlight_color", error)); ambient = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("ambient", error)); //lightnorm = LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error); - gamma = LLWLParamManager::getInstance()->mCurParams.getVector("gamma", error)[0]; + gamma = LLWLParamManager::getInstance()->mCurParams.getFloat("gamma", error); blue_density = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_density", error)); blue_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_horizon", error)); - haze_density = LLWLParamManager::getInstance()->mCurParams.getVector("haze_density", error)[0]; - haze_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("haze_horizon", error)); - density_multiplier = LLWLParamManager::getInstance()->mCurParams.getVector("density_multiplier", error)[0]; - max_y = LLWLParamManager::getInstance()->mCurParams.getVector("max_y", error)[0]; + haze_density = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_density", error); + haze_horizon = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_horizon", error); + density_multiplier = LLWLParamManager::getInstance()->mCurParams.getFloat("density_multiplier", error); + max_y = LLWLParamManager::getInstance()->mCurParams.getFloat("max_y", error); glow = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("glow", error)); - cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_shadow", error)[0]; + cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_shadow", error); cloud_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_color", error)); - cloud_scale = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_scale", error)[0]; + cloud_scale = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_scale", error); cloud_pos_density1 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density1", error)); cloud_pos_density2 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density2", error)); @@ -825,7 +825,7 @@ void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLCo // Haze color above cloud vary_HazeColor = (blue_horizon * blue_weight * (sunlight + ambient) - + componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + ambient) + + componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + ambient) ); // Increase ambient when there are more clouds @@ -836,7 +836,7 @@ void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLCo // Haze color below cloud LLColor3 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient) - + componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + tmpAmbient) + + componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + tmpAmbient) ); // Final atmosphere additive @@ -1002,7 +1002,7 @@ void LLVOSky::calcAtmospherics(void) //haze color vary_HazeColor = (blue_horizon * blue_weight * (sunlight*(1.f - cloud_shadow) + tmpAmbient) - + componentMult(haze_horizon.mV[0] * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient) + + componentMult(haze_horizon * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient) ); //brightness of surface both sunlight and ambient diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index d3a42583ea..6e6898d80a 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -410,7 +410,7 @@ public: LLColor3 blue_density; LLColor3 blue_horizon; F32 haze_density; - LLColor3 haze_horizon; + F32 haze_horizon; F32 density_multiplier; F32 max_y; LLColor3 glow; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7492a06784..080d1f774a 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4123,6 +4123,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mGeometryBytes = 0; group->mSurfaceArea = 0; + //cache object box size since it might be used for determining visibility + group->mObjectBoxSize = group->mObjectBounds[1].getLength3().getF32(); + group->clearDrawMap(); mFaceList.clear(); @@ -4433,10 +4436,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) 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); } + alpha_faces.push_back(facep); } } else @@ -4714,11 +4717,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: buffer_index = -1; } - S32 texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity + S32 texture_index_channels = 1; - if (gGLManager.mGLVersion < 3.1f) + if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) { - texture_index_channels = 1; + texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity; } if (LLPipeline::sRenderDeferred && distance_sort) @@ -4939,6 +4942,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: fullbright = TRUE; } + if (hud_group) + { //all hud attachments are fullbright + fullbright = TRUE; + } + const LLTextureEntry* te = facep->getTextureEntry(); tex = facep->getTexture(); @@ -4947,7 +4955,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: if (is_alpha) { // can we safely treat this as an alpha mask? - if (facep->canRenderAsMask()) + if (facep->getFaceColor().mV[3] <= 0.f) + { //100% transparent, don't render unless we're highlighting transparent + registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); + } + else if (facep->canRenderAsMask()) { if (te->getFullbright() || LLPipeline::sNoAlpha) { @@ -4964,7 +4976,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } } else if (gPipeline.canUseVertexShaders() - && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD && LLPipeline::sRenderBump && te->getShiny()) { //shiny @@ -5029,9 +5040,12 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } } - //not sure why this is here -- shiny HUD attachments maybe? -- davep 5/11/2010 - if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump) - { + + if (!gPipeline.canUseVertexShaders() && + !is_alpha && + te->getShiny() && + LLPipeline::sRenderBump) + { //shiny as an extra pass when shaders are disabled registerFace(group, facep, LLRenderPass::PASS_SHINY); } } diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 315616e8a5..cd78157944 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -160,7 +160,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) static const unsigned int vertices_per_quad = 4; static const unsigned int indices_per_quad = 6; - const S32 size = gSavedSettings.getBOOL("RenderTransparentWater") && !LLGLSLShader::sNoFixedFunction ? 16 : 1; + const S32 size = gSavedSettings.getBOOL("RenderTransparentWater") && LLGLSLShader::sNoFixedFunction ? 16 : 1; const S32 num_quads = size * size; face->setSize(vertices_per_quad * num_quads, @@ -197,6 +197,13 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) F32 size_inv = 1.f / size; + F32 z_fudge = 0.f; + + if (getIsEdgePatch()) + { //bump edge patches down 10 cm to prevent aliasing along edges + z_fudge = -0.1f; + } + for (y = 0; y < size; y++) { for (x = 0; x < size; x++) @@ -205,6 +212,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) position_agent = getPositionAgent() - getScale() * 0.5f; position_agent.mV[VX] += (x + 0.5f) * step_x; position_agent.mV[VY] += (y + 0.5f) * step_y; + position_agent.mV[VZ] += z_fudge; *verticesp++ = position_agent - right + up; *verticesp++ = position_agent - right - up; diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 20b34637b8..e386112334 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -194,7 +194,7 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader) shader->uniform4fv("waterPlane", 1, mWaterPlane.mV); shader->uniform1f("waterFogDensity", getFogDensity()); shader->uniform1f("waterFogKS", mWaterFogKS); - shader->uniform4f("distance_multiplier", 0, 0, 0, 0); + shader->uniform1f("distance_multiplier", 0); } } diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index d8aa0b7d5c..402504933c 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -221,7 +221,7 @@ void LLWearable::createVisualParams() param->resetDrivenParams(); if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) { - if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp,_1 ), true)) + if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp.get(),_1 ), true)) { llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; continue; @@ -810,6 +810,20 @@ const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const return NULL; } +std::vector<LLLocalTextureObject*> LLWearable::getLocalTextureListSeq() +{ + std::vector<LLLocalTextureObject*> result; + + for(te_map_t::const_iterator iter = mTEMap.begin(); + iter != mTEMap.end(); iter++) + { + LLLocalTextureObject* lto = iter->second; + result.push_back(lto); + } + + return result; +} + void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) { if( mTEMap.find(index) != mTEMap.end() ) diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index fd614ade64..3d8c53a755 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -106,6 +106,7 @@ public: LLLocalTextureObject* getLocalTextureObject(S32 index); const LLLocalTextureObject* getLocalTextureObject(S32 index) const; + std::vector<LLLocalTextureObject*> getLocalTextureListSeq(); void setLocalTextureObject(S32 index, LLLocalTextureObject <o); void addVisualParam(LLVisualParam *param); diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 55608a059f..49d9d44d74 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -64,7 +64,6 @@ LLWLParamManager::LLWLParamManager() : //set the defaults for the controls - // index is from sWLUniforms in pipeline.cpp line 979 /// Sun Delta Terrain tweak variables. mSunDeltaYaw(180.0f), @@ -72,10 +71,10 @@ LLWLParamManager::LLWLParamManager() : mWLGamma(1.0f, "gamma"), mBlueHorizon(0.25f, 0.25f, 1.0f, 1.0f, "blue_horizon", "WLBlueHorizon"), - mHazeDensity(1.0f, 1.0f, 1.0f, 0.5f, "haze_density"), + mHazeDensity(1.0f, "haze_density"), mBlueDensity(0.25f, 0.25f, 0.25f, 1.0f, "blue_density", "WLBlueDensity"), mDensityMult(1.0f, "density_multiplier", 1000), - mHazeHorizon(1.0f, 1.0f, 1.0f, 0.5f, "haze_horizon"), + mHazeHorizon(1.0f, "haze_horizon"), mMaxAlt(4000.0f, "max_y"), // Lighting diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index bc984b9126..72422500fc 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -102,9 +102,8 @@ struct WLFloatControl { { } - inline WLFloatControl & operator = (LLVector4 const & val) { - x = val.mV[0]; - + inline WLFloatControl & operator = (F32 val) { + x = val; return *this; } @@ -340,10 +339,10 @@ public: /// Atmospherics WLColorControl mBlueHorizon; - WLColorControl mHazeDensity; + WLFloatControl mHazeDensity; WLColorControl mBlueDensity; WLFloatControl mDensityMult; - WLColorControl mHazeHorizon; + WLFloatControl mHazeHorizon; WLFloatControl mMaxAlt; /// Lighting diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp index 5bb7025031..b04d30db55 100644 --- a/indra/newview/llwlparamset.cpp +++ b/indra/newview/llwlparamset.cpp @@ -41,33 +41,7 @@ LLWLParamSet::LLWLParamSet(void) : mName("Unnamed Preset"), mCloudScrollXOffset(0.f), mCloudScrollYOffset(0.f) -{ -/* REMOVE or init the LLSD - const std::map<std::string, LLVector4>::value_type hardcodedPreset[] = { - std::make_pair("lightnorm", LLVector4(0.f, 0.707f, -0.707f, 0.f)), - std::make_pair("sunlight_color", LLVector4(0.6f, 0.6f, 2.83f, 2.27f)), - std::make_pair("ambient", LLVector4(0.27f, 0.33f, 0.44f, 1.19f)), - std::make_pair("blue_horizon", LLVector4(0.3f, 0.4f, 0.9f, 1.f)), - std::make_pair("blue_density", LLVector4(0.3f, 0.4f, 0.8f, 1.f)), - std::make_pair("haze_horizon", LLVector4(0.6f, 0.6f, 0.6f, 1.f)), - std::make_pair("haze_density", LLVector4(0.3f, 0.3f, 0.3f, 1.f)), - std::make_pair("cloud_shadow", LLVector4(0.f, 0.f, 0.f, 0.f)), - std::make_pair("density_multiplier", LLVector4(0.001f, 0.001f, 0.001f, 0.001f)), - std::make_pair("distance_multiplier", LLVector4(1.f, 1.f, 1.f, 1.f)), - std::make_pair("max_y", LLVector4(600.f, 600.f, 600.f, 0.f)), - std::make_pair("glow", LLVector4(15.f, 0.001f, -0.03125f, 0.f)), - std::make_pair("cloud_color", LLVector4(0.0f, 0.0f, 0.0f, 0.0f)), - std::make_pair("cloud_pos_density1", LLVector4(0.f, 0.f, 0.f, 1.f)), - std::make_pair("cloud_pos_density2", LLVector4(0.f, 0.f, 0.f, 1.f)), - std::make_pair("cloud_scale", LLVector4(0.42f, 0.f, 0.f, 1.f)), - std::make_pair("gamma", LLVector4(2.0f, 2.0f, 2.0f, 0.0f)), - }; - std::map<std::string, LLVector4>::value_type const * endHardcodedPreset = - hardcodedPreset + LL_ARRAY_SIZE(hardcodedPreset); - - mParamValues.insert(hardcodedPreset, endHardcodedPreset); -*/ -} +{} static LLFastTimer::DeclareTimer FTM_WL_PARAM_UPDATE("WL Param Update"); @@ -79,55 +53,78 @@ void LLWLParamSet::update(LLGLSLShader * shader) const i != mParamValues.endMap(); ++i) { - - const std::string& param = i->first; - if( param == "star_brightness" || param == "preset_num" || param == "sun_angle" || + if (param == "star_brightness" || param == "preset_num" || param == "sun_angle" || param == "east_angle" || param == "enable_cloud_scroll" || param == "cloud_scroll_rate" || param == "lightnorm" ) { continue; } - if(param == "cloud_pos_density1") + if (param == "cloud_pos_density1") { LLVector4 val; val.mV[0] = F32(i->second[0].asReal()) + mCloudScrollXOffset; val.mV[1] = F32(i->second[1].asReal()) + mCloudScrollYOffset; val.mV[2] = (F32) i->second[2].asReal(); val.mV[3] = (F32) i->second[3].asReal(); + stop_glerror(); shader->uniform4fv(param, 1, val.mV); stop_glerror(); - } + } + else if (param == "cloud_scale" || param == "cloud_shadow" || + param == "density_multiplier" || param == "distance_multiplier" || + param == "haze_density" || param == "haze_horizon" || + param == "max_y" ) + { + F32 val = (F32) i->second[0].asReal(); + + stop_glerror(); + shader->uniform1f(param, val); + stop_glerror(); + } else // param is the uniform name { - LLVector4 val; - // handle all the different cases - if(i->second.isArray() && i->second.size() == 4) + if (i->second.isArray() && i->second.size() == 4) { + LLVector4 val; + val.mV[0] = (F32) i->second[0].asReal(); val.mV[1] = (F32) i->second[1].asReal(); val.mV[2] = (F32) i->second[2].asReal(); val.mV[3] = (F32) i->second[3].asReal(); + + stop_glerror(); + shader->uniform4fv(param, 1, val.mV); + stop_glerror(); } - else if(i->second.isReal()) + else if (i->second.isReal()) { - val.mV[0] = (F32) i->second.asReal(); + F32 val = (F32) i->second.asReal(); + + stop_glerror(); + shader->uniform1f(param, val); + stop_glerror(); } - else if(i->second.isInteger()) + else if (i->second.isInteger()) { - val.mV[0] = (F32) i->second.asReal(); + S32 val = (S32) i->second.asInteger(); + + stop_glerror(); + shader->uniform1i(param, val); + stop_glerror(); } - else if(i->second.isBoolean()) + else if (i->second.isBoolean()) { - val.mV[0] = i->second.asBoolean(); + S32 val = (i->second.asBoolean() ? 1 : 0); + + stop_glerror(); + shader->uniform1i(param, val); + stop_glerror(); } - stop_glerror(); - shader->uniform4fv(param, 1, val.mV); - stop_glerror(); } } } @@ -148,7 +145,8 @@ void LLWLParamSet::set(const std::string& paramName, float x) } } -void LLWLParamSet::set(const std::string& paramName, float x, float y) { +void LLWLParamSet::set(const std::string& paramName, float x, float y) +{ mParamValues[paramName][0] = x; mParamValues[paramName][1] = y; } @@ -194,7 +192,6 @@ void LLWLParamSet::set(const std::string& paramName, const LLColor4 & val) LLVector4 LLWLParamSet::getVector(const std::string& paramName, bool& error) { - // test to see if right type LLSD cur_val = mParamValues.get(paramName); if (!cur_val.isArray()) @@ -215,7 +212,6 @@ LLVector4 LLWLParamSet::getVector(const std::string& paramName, bool& error) F32 LLWLParamSet::getFloat(const std::string& paramName, bool& error) { - // test to see if right type LLSD cur_val = mParamValues.get(paramName); if (cur_val.isArray() && cur_val.size() != 0) @@ -234,8 +230,6 @@ F32 LLWLParamSet::getFloat(const std::string& paramName, bool& error) return 0; } - - void LLWLParamSet::setSunAngle(float val) { // keep range 0 - 2pi @@ -263,7 +257,6 @@ void LLWLParamSet::setEastAngle(float val) mParamValues["east_angle"] = val; } - void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) { // set up the iterators @@ -282,7 +275,6 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) // Iterate through values for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter) { - // If param exists in both src and dest, set the holder variables, otherwise skip if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first)) { diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h index 3c44ed3bb8..b087119dd5 100644 --- a/indra/newview/llwlparamset.h +++ b/indra/newview/llwlparamset.h @@ -110,7 +110,7 @@ public: /// \param error A flag to set if it's not the proper return type LLVector4 getVector(const std::string& paramName, bool& error); - /// Get an integer parameter + /// Get a float parameter /// \param paramName The name of the parameter to set. /// \param error A flag to set if it's not the proper return type F32 getFloat(const std::string& paramName, bool& error); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 676287c0ad..b061c90d98 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -839,7 +839,6 @@ void LLWorld::updateWaterObjects() // Now, get a list of the holes S32 x, y; - F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f; for (x = min_x; x <= max_x; x += rwidth) { for (y = min_y; y <= max_y; y += rwidth) @@ -851,7 +850,7 @@ void LLWorld::updateWaterObjects() waterp->setUseTexture(FALSE); waterp->setPositionGlobal(LLVector3d(x + rwidth/2, y + rwidth/2, - water_height)); + 256.f+DEFAULT_WATER_HEIGHT)); waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); gPipeline.createObject(waterp); mHoleWaterObjects.push_back(waterp); @@ -908,7 +907,7 @@ void LLWorld::updateWaterObjects() } waterp->setRegion(gAgent.getRegion()); - LLVector3d water_pos(water_center_x, water_center_y, water_height) ; + LLVector3d water_pos(water_center_x, water_center_y, 256.f+DEFAULT_WATER_HEIGHT) ; LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f); //stretch out to horizon @@ -1161,24 +1160,13 @@ void send_agent_resume() static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin) { - LLVector3d pos_global; - LLVector3 pos_local; - U8 bits; + LLVector3d pos_local; - bits = compact_local & 0xFF; - pos_local.mV[VZ] = F32(bits) * 4.f; - compact_local >>= 8; + pos_local.mdV[VZ] = (compact_local & 0xFFU) * 4; + pos_local.mdV[VY] = (compact_local >> 8) & 0xFFU; + pos_local.mdV[VX] = (compact_local >> 16) & 0xFFU; - bits = compact_local & 0xFF; - pos_local.mV[VY] = (F32)bits; - compact_local >>= 8; - - bits = compact_local & 0xFF; - pos_local.mV[VX] = (F32)bits; - - pos_global.setVec( pos_local ); - pos_global += region_origin; - return pos_global; + return region_origin + pos_local; } void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const @@ -1199,22 +1187,22 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; - if(!pVOAvatar->isDead() && !pVOAvatar->isSelf()) + + if (!pVOAvatar->isDead() && !pVOAvatar->isSelf()) { + LLVector3d pos_global = pVOAvatar->getPositionGlobal(); LLUUID uuid = pVOAvatar->getID(); - if(!uuid.isNull()) + + if (!uuid.isNull() + && dist_vec_squared(pos_global, relative_to) <= radius_squared) { - LLVector3d pos_global = pVOAvatar->getPositionGlobal(); - if(dist_vec_squared(pos_global, relative_to) <= radius_squared) + if(positions != NULL) { - if(positions != NULL) - { - positions->push_back(pos_global); - } - if(avatar_ids !=NULL) - { - avatar_ids->push_back(uuid); - } + positions->push_back(pos_global); + } + if(avatar_ids !=NULL) + { + avatar_ids->push_back(uuid); } } } @@ -1233,9 +1221,9 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi { LLUUID uuid = regionp->mMapAvatarIDs.get(i); // if this avatar doesn't already exist in the list, add it - if(uuid.notNull() && avatar_ids!=NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end()) + if(uuid.notNull() && avatar_ids != NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end()) { - if(positions != NULL) + if (positions != NULL) { positions->push_back(pos_global); } @@ -1246,6 +1234,11 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi } } +bool LLWorld::isRegionListed(const LLViewerRegion* region) const +{ + region_list_t::const_iterator it = find(mRegionList.begin(), mRegionList.end(), region); + return it != mRegionList.end(); +} LLHTTPRegistration<LLEstablishAgentCommunication> gHTTPRegistrationEstablishAgentCommunication( diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index d8ab4bc508..f350009d10 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -157,6 +157,11 @@ public: std::vector<LLVector3d>* positions = NULL, const LLVector3d& relative_to = LLVector3d(), F32 radius = FLT_MAX) const; + // Returns 'true' if the region is in mRegionList, + // 'false' if the region has been removed due to region change + // or if the circuit to this simulator had been lost. + bool isRegionListed(const LLViewerRegion* region) const; + private: region_list_t mActiveRegionList; region_list_t mRegionList; diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index e50851b8e7..a3ccf87cfc 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -77,6 +77,7 @@ LLUIImagePtr LLWorldMapView::sAvatarYouLargeImage = NULL; LLUIImagePtr LLWorldMapView::sAvatarLevelImage = NULL; LLUIImagePtr LLWorldMapView::sAvatarAboveImage = NULL; LLUIImagePtr LLWorldMapView::sAvatarBelowImage = NULL; +LLUIImagePtr LLWorldMapView::sAvatarUnknownImage = NULL; LLUIImagePtr LLWorldMapView::sTelehubImage = NULL; LLUIImagePtr LLWorldMapView::sInfohubImage = NULL; @@ -120,6 +121,7 @@ void LLWorldMapView::initClass() sAvatarLevelImage = LLUI::getUIImage("map_avatar_32.tga"); sAvatarAboveImage = LLUI::getUIImage("map_avatar_above_32.tga"); sAvatarBelowImage = LLUI::getUIImage("map_avatar_below_32.tga"); + sAvatarUnknownImage = LLUI::getUIImage("map_avatar_unknown_32.tga"); sHomeImage = LLUI::getUIImage("map_home.tga"); sTelehubImage = LLUI::getUIImage("map_telehub.tga"); @@ -149,6 +151,7 @@ void LLWorldMapView::cleanupClass() sAvatarLevelImage = NULL; sAvatarAboveImage = NULL; sAvatarBelowImage = NULL; + sAvatarUnknownImage = NULL; sTelehubImage = NULL; sInfohubImage = NULL; @@ -513,7 +516,7 @@ void LLWorldMapView::draw() TRUE, "You are here", "", - llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking + LLFontGL::getFontSansSerifSmall()->getLineHeight()); // offset vertically by one line, to avoid overlap with target tracking } // Draw the current agent viewing angle @@ -992,7 +995,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& const S32 TEXT_PADDING = DEFAULT_TRACKING_ARROW_SIZE + 2; S32 half_text_width = llfloor(font->getWidthF32(label) * 0.5f); text_x = llclamp(text_x, half_text_width + TEXT_PADDING, getRect().getWidth() - half_text_width - TEXT_PADDING); - text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - llround(font->getLineHeight()) - TEXT_PADDING - vert_offset); + text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - font->getLineHeight() - TEXT_PADDING - vert_offset); if (label != "") { @@ -1005,7 +1008,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& if (tooltip != "") { - text_y -= (S32)font->getLineHeight(); + text_y -= font->getLineHeight(); font->renderUTF8( tooltip, 0, @@ -1147,17 +1150,25 @@ void LLWorldMapView::drawAvatar(F32 x_pixels, F32 y_pixels, const LLColor4& color, F32 relative_z, - F32 dot_radius) + F32 dot_radius, + bool unknown_relative_z) { const F32 HEIGHT_THRESHOLD = 7.f; LLUIImagePtr dot_image = sAvatarLevelImage; - if(relative_z < -HEIGHT_THRESHOLD) + if (unknown_relative_z) { - dot_image = sAvatarBelowImage; + dot_image = sAvatarUnknownImage; } - else if(relative_z > HEIGHT_THRESHOLD) - { - dot_image = sAvatarAboveImage; + else + { + if(relative_z < -HEIGHT_THRESHOLD) + { + dot_image = sAvatarBelowImage; + } + else if(relative_z > HEIGHT_THRESHOLD) + { + dot_image = sAvatarAboveImage; + } } S32 dot_width = llround(dot_radius * 2.f); dot_image->draw(llround(x_pixels - dot_radius), @@ -1203,7 +1214,7 @@ void LLWorldMapView::drawIconName(F32 x_pixels, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); - text_y -= llround(LLFontGL::getFontSansSerif()->getLineHeight()); + text_y -= LLFontGL::getFontSansSerif()->getLineHeight(); // render text LLFontGL::getFontSansSerif()->renderUTF8(second_line, 0, diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index 9ab53b1ba3..a2a6dc53fb 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -112,7 +112,8 @@ public: F32 y_pixels, const LLColor4& color, F32 relative_z = 0.f, - F32 dot_radius = 3.f); + F32 dot_radius = 3.f, + bool reached_max_z = false); static void drawIconName(F32 x_pixels, F32 y_pixels, const LLColor4& color, @@ -138,6 +139,7 @@ public: static LLUIImagePtr sAvatarLevelImage; static LLUIImagePtr sAvatarAboveImage; static LLUIImagePtr sAvatarBelowImage; + static LLUIImagePtr sAvatarUnknownImage; static LLUIImagePtr sTelehubImage; static LLUIImagePtr sInfohubImage; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c523a78b22..ed636a40b2 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -187,6 +187,7 @@ F32 LLPipeline::RenderShadowFOVCutoff; BOOL LLPipeline::CameraOffset; F32 LLPipeline::CameraMaxCoF; F32 LLPipeline::CameraDoFResScale; +F32 LLPipeline::RenderAutoHideSurfaceAreaLimit; const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f; @@ -203,10 +204,6 @@ extern S32 gBoxFrame; extern BOOL gDisplaySwapBuffers; extern BOOL gDebugGL; -// hack counter for rendering a fixed number of frames after toggling -// fullscreen to work around DEV-5361 -static S32 sDelayedVBOEnable = 0; - BOOL gAvatarBacklight = FALSE; BOOL gDebugPipeline = FALSE; @@ -411,6 +408,7 @@ LLPipeline::LLPipeline() : mOldRenderDebugMask(0), mGroupQ1Locked(false), mGroupQ2Locked(false), + mResetVertexBuffers(false), mLastRebuildPool(NULL), mAlphaPool(NULL), mSkyPool(NULL), @@ -595,6 +593,7 @@ void LLPipeline::init() gSavedSettings.getControl("CameraOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("CameraMaxCoF")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("CameraDoFResScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } LLPipeline::~LLPipeline() @@ -692,8 +691,6 @@ void LLPipeline::destroyGL() if (LLVertexBuffer::sEnableVBOs) { - // render 30 frames after switching to work around DEV-5361 - sDelayedVBOEnable = 30; LLVertexBuffer::sEnableVBOs = FALSE; } } @@ -816,6 +813,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (LLPipeline::sRenderDeferred) { + // Set this flag in case we crash while resizing window or allocating space for deferred rendering targets + gSavedSettings.setBOOL("RenderInitError", TRUE); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); + S32 shadow_detail = RenderShadowDetail; BOOL ssao = RenderDeferredSSAO; @@ -847,9 +848,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 0) { //allocate 4 sun shadow maps + U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur for (U32 i = 0; i < 4; i++) { - if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; + if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; } } else @@ -865,9 +867,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 1) { //allocate two spot shadow maps + U32 spot_shadow_map_width = width; for (U32 i = 4; i < 6; i++) { - if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false; + if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false; } } else @@ -877,6 +880,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mShadow[i].release(); } } + + // don't disable shaders on next session + gSavedSettings.setBOOL("RenderInitError", FALSE); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); } else { @@ -1012,6 +1019,7 @@ void LLPipeline::refreshCachedSettings() CameraOffset = gSavedSettings.getBOOL("CameraOffset"); CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF"); CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale"); + RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); updateRenderDeferred(); } @@ -1032,11 +1040,7 @@ void LLPipeline::releaseGLBuffers() mTrueNoiseMap = 0; } - if (mLightFunc) - { - LLImageGL::deleteTextures(1, &mLightFunc); - mLightFunc = 0; - } + releaseLUTBuffers(); mWaterRef.release(); mWaterDis.release(); @@ -1052,6 +1056,15 @@ void LLPipeline::releaseGLBuffers() LLVOAvatar::resetImpostors(); } +void LLPipeline::releaseLUTBuffers() +{ + if (mLightFunc) + { + LLImageGL::deleteTextures(1, &mLightFunc); + mLightFunc = 0; + } +} + void LLPipeline::releaseScreenBuffers() { mUIScreen.release(); @@ -1081,10 +1094,11 @@ void LLPipeline::createGLBuffers() if (LLPipeline::sWaterReflections) { //water reflection texture - U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution"); + U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE); - mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE); + //always use FBO for mWaterDis so it can be used for avatar texture bakes + mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); } mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); @@ -1127,7 +1141,7 @@ void LLPipeline::createGLBuffers() LLImageGL::generateTextures(1, &mNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } @@ -1142,54 +1156,73 @@ void LLPipeline::createGLBuffers() LLImageGL::generateTextures(1, &mTrueNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } + createLUTBuffers(); + } + + gBumpImageList.restoreGL(); +} + +void LLPipeline::createLUTBuffers() +{ + if (sRenderDeferred) + { if (!mLightFunc) { U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); - U8* lg = new U8[lightResX*lightResY]; - + U8* ls = new U8[lightResX*lightResY]; + F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); + // Calculate the (normalized) Blinn-Phong specular lookup texture. for (U32 y = 0; y < lightResY; ++y) { for (U32 x = 0; x < lightResX; ++x) { - //spec func + ls[y*lightResX+x] = 0; F32 sa = (F32) x/(lightResX-1); F32 spec = (F32) y/(lightResY-1); - //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255); - - //F32 sp = acosf(sa)/(1.f-spec); - - sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent")); - F32 a = acosf(sa*0.25f+0.75f); - F32 m = llmax(0.5f-spec*0.5f, 0.001f); - F32 t2 = tanf(a)/m; - t2 *= t2; - - F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f; - F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2); - - lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255); + F32 n = spec * spec * specExp; + + // Nothing special here. Just your typical blinn-phong term. + spec = powf(sa, n); + + // Apply our normalization function. + // Note: This is the full equation that applies the full normalization curve, not an approximation. + // This is fine, given we only need to create our LUT once per buffer initialization. + // The only trade off is we have a really low dynamic range. + // This means we have to account for things not being able to exceed 0 to 1 in our shaders. + spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); + + // Always sample at a 1.0/2.2 curve. + // This "Gamma corrects" our specular term, boosting our lower exponent reflections. + spec = powf(spec, 1.f/2.2f); + + // Easy fix for our dynamic range problem: divide by 6 here, multiply by 6 in our shaders. + // This allows for our specular term to exceed a value of 1 in our shaders. + // This is something that can be important for energy conserving specular models where higher exponents can result in highlights that exceed a range of 0 to 1. + // Technically, we could just use an R16F texture, but driver support for R16F textures can be somewhat spotty at times. + // This works remarkably well for higher specular exponents, though banding can sometimes be seen on lower exponents. + // Combined with a bit of noise and trilinear filtering, the banding is hardly noticable. + ls[y*lightResX+x] = (U8)(llclamp(spec * (1.f / 6), 0.f, 1.f) * 255); } } - + LLImageGL::generateTextures(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, lg); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - - delete [] lg; + + delete [] ls; } } - - gBumpImageList.restoreGL(); } -void LLPipeline::restoreGL() + +void LLPipeline::restoreGL() { LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL); assertInitialized(); @@ -2523,15 +2556,6 @@ void LLPipeline::updateGeom(F32 max_dtime) assertInitialized(); - if (sDelayedVBOEnable > 0) - { - if (--sDelayedVBOEnable <= 0) - { - resetVertexBuffers(); - LLVertexBuffer::sEnableVBOs = TRUE; - } - } - // notify various object types to reset internal cost metrics, etc. // for now, only LLVOVolume does this to throttle LOD changes LLVOVolume::preUpdateGeom(); @@ -3346,7 +3370,9 @@ void LLPipeline::postSort(LLCamera& camera) { LLSpatialGroup* group = *i; if (sUseOcclusion && - group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + group->isOcclusionState(LLSpatialGroup::OCCLUDED) || + (RenderAutoHideSurfaceAreaLimit > 0.f && + group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit*llmax(group->mObjectBoxSize, 10.f))) { continue; } @@ -6185,7 +6211,7 @@ LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj) void LLPipeline::resetVertexBuffers(LLDrawable* drawable) { - if (!drawable || drawable->isDead()) + if (!drawable) { return; } @@ -6198,7 +6224,19 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) } void LLPipeline::resetVertexBuffers() -{ +{ + mResetVertexBuffers = true; +} + +void LLPipeline::doResetVertexBuffers() +{ + if (!mResetVertexBuffers) + { + return; + } + + mResetVertexBuffers = false; + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -6224,11 +6262,9 @@ void LLPipeline::resetVertexBuffers() if (LLVertexBuffer::sGLCount > 0) { - llwarns << "VBO wipe failed." << llendl; + llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; } - llassert(LLVertexBuffer::sGLCount == 0); - LLVertexBuffer::unbind(); sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); @@ -6646,9 +6682,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) mDeferredLight.flush(); } + U32 dof_width = (U32) (mScreen.getWidth()*CameraDoFResScale); + U32 dof_height = (U32) (mScreen.getHeight()*CameraDoFResScale); + { //perform DoF sampling at half-res (preserve alpha channel) mScreen.bindTarget(); - glViewport(0,0,(GLsizei) (mScreen.getWidth()*CameraDoFResScale), (GLsizei) (mScreen.getHeight()*CameraDoFResScale)); + glViewport(0,0, dof_width, dof_height); gGL.setColorMask(true, false); shader = &gDeferredPostProgram; @@ -6661,7 +6700,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); @@ -6706,6 +6745,8 @@ 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); + shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1); + shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height-1); gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); @@ -8259,7 +8300,7 @@ static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows"); static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow"); static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow"); -void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion) +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion, U32 target_width) { LLFastTimer t(FTM_SHADOW_RENDER); @@ -8350,7 +8391,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLFastTimer ftm(FTM_SHADOW_ALPHA); gDeferredShadowAlphaMaskProgram.bind(); gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); - + gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | @@ -8815,16 +8857,16 @@ 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; x = powf(x, sxp); mSunClipPlanes.mV[i] = near_clip+range*x; } + + mSunClipPlanes.mV[0] *= 1.25f; //bump back first split for transition padding } // convenience array of 4 near clip plane distances @@ -8881,8 +8923,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f; delta.normVec(); F32 dp = delta*pn; - frust[i] = eye + (delta*dist[j]*0.95f)/dp; - frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp; + frust[i] = eye + (delta*dist[j]*0.75f)/dp; + frust[i+4] = eye + (delta*dist[j+1]*1.25f)/dp; } shadow_cam.calcAgentFrustumPlanes(frust); @@ -9203,11 +9245,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[j].getViewport(gGLViewport); mShadow[j].clear(); + U32 target_width = mShadow[j].getWidth(); + { static LLCullResult result[4]; //LLGLEnable enable(GL_DEPTH_CLAMP_NV); - renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE); + renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width); } mShadow[j].flush(); @@ -9346,11 +9390,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[i+4].getViewport(gGLViewport); mShadow[i+4].clear(); + U32 target_width = mShadow[i+4].getWidth(); + static LLCullResult result[2]; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4; - renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE); + renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width); mShadow[i+4].flush(); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 9c78048c46..5c623fc9f2 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -111,10 +111,13 @@ public: void destroyGL(); void restoreGL(); void resetVertexBuffers(); + void doResetVertexBuffers(); void resizeScreenTexture(); void releaseGLBuffers(); + void releaseLUTBuffers(); void releaseScreenBuffers(); void createGLBuffers(); + void createLUTBuffers(); void allocateScreenBuffer(U32 resX, U32 resY); bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); @@ -261,7 +264,7 @@ public: void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; } - void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader = TRUE, BOOL use_occlusion = TRUE); + void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader, BOOL use_occlusion, U32 target_width); void renderHighlights(); void renderDebug(); void renderPhysicsDisplay(); @@ -461,6 +464,7 @@ public: RENDER_DEBUG_LOD_INFO = 0x04000000, RENDER_DEBUG_RENDER_COMPLEXITY = 0x08000000, RENDER_DEBUG_ATTACHMENT_BYTES = 0x10000000, + RENDER_DEBUG_TEXEL_DENSITY = 0x20000000 }; public: @@ -653,6 +657,8 @@ protected: bool mGroupQ2Locked; bool mGroupQ1Locked; + bool mResetVertexBuffers; //if true, clear vertex buffers on next update + LLViewerObject::vobj_list_t mCreateQ; LLDrawable::drawable_set_t mRetexturedList; @@ -846,6 +852,7 @@ public: static BOOL CameraOffset; static F32 CameraMaxCoF; static F32 CameraDoFResScale; + static F32 RenderAutoHideSurfaceAreaLimit; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 8baaa14595..b616e2327b 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -615,6 +615,9 @@ name="PanelFocusBackgroundColor" reference="DkGray2" /> <color + name="PanelNotificationBackground" + value="1 0.3 0.3 0" /> + <color name="ParcelHoverColor" reference="White" /> <color @@ -747,6 +750,9 @@ name="TitleBarFocusColor" reference="White_10" /> <color + name="ToastBackground" + value="0.3 0.3 0.3 0" /> + <color name="ToolTipBgColor" value="0.937 0.89 0.655 1" /> <color diff --git a/indra/newview/skins/default/textures/checker.png b/indra/newview/skins/default/textures/checker.png Binary files differnew file mode 100644 index 0000000000..1ab87e3f02 --- /dev/null +++ b/indra/newview/skins/default/textures/checker.png diff --git a/indra/newview/skins/default/textures/map_avatar_unknown_32.tga b/indra/newview/skins/default/textures/map_avatar_unknown_32.tga Binary files differnew file mode 100644 index 0000000000..d1192478c6 --- /dev/null +++ b/indra/newview/skins/default/textures/map_avatar_unknown_32.tga diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index e4a8622a4b..eabcc68916 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -122,6 +122,8 @@ with the same filename but different name <texture name="Checkbox_Press" file_name="widgets/Checkbox_Press.png" preload="true" /> <texture name="Check_Mark" file_name="icons/check_mark.png" preload="true" /> + <texture name="Checker" file_name="checker.png" preload="false" /> + <texture name="Command_AboutLand_Icon" file_name="toolbar_icons/land.png" preload="true" /> <texture name="Command_Appearance_Icon" file_name="toolbar_icons/appearance.png" preload="true" /> <texture name="Command_Avatar_Icon" file_name="toolbar_icons/avatars.png" preload="true" /> 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_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml index b893ab79e5..9e330f9766 100644 --- a/indra/newview/skins/default/xui/de/floater_about_land.xml +++ b/indra/newview/skins/default/xui/de/floater_about_land.xml @@ -374,7 +374,7 @@ Nur große Parzellen können in der Suche aufgeführt werden. </text> <texture_picker label="" name="snapshot_ctrl" tool_tip="Klicken Sie hier, um ein Bild auszuwählen"/> <text name="allow_label5"> - Avatare auf dieser Parzelle sehen und mit ihnen chatten + Avatare in anderen Parzellen können Avatare in dieser Parzelle sehen und mit ihnen chatten </text> <check_box label="Avatare sehen" name="SeeAvatarsCheck" tool_tip="Gestattet sowohl Avataren auf anderen Parzellen, Avatare auf dieser Parzelle zu sehen und mit ihnen zu chatten, als auch Ihnen, diese Avatare auf anderen Parzellen zu sehen und mit ihnen zu chatten."/> <text name="landing_point"> @@ -458,12 +458,12 @@ Nur große Parzellen können in der Suche aufgeführt werden. <text name="Limit access to this parcel to:"> Zugang zu dieser Parzelle </text> - <check_box label="Öffentlichen Zugang erlauben [MATURITY]" name="public_access"/> + <check_box label="Öffentlichen Zugang gestatten (bei Deaktivierung dieser Option werden Bannlinien generiert)" name="public_access"/> <text name="Only Allow" width="400"> - Zugang auf Einwohner beschränken, die überprüft wurden von: + Zugang nur Einwohnern gestatten, die: </text> - <check_box label="Zahlungsinformation gespeichert [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Einwohner ohne Zahlungsinformation nicht zulassen."/> - <check_box label="Altersüberprüfung [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Einwohner ohne Altersüberprüfung nicht zulassen. Weitere Informationen finden Sie im [SUPPORT_SITE]."/> + <check_box label="Zahlungsinformationen hinterlegt haben [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Um diese Parzelle besuchen zu können, müssen Einwohner Zahlungsinformationen hinterlegt haben. Weitere Informationen finden Sie auf [SUPPORT_SITE]."/> + <check_box label="ihr Alter bestätigt haben [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Um diese Parzelle besuchen zu können, müssen Einwohner ihr Alter bestätigt haben. Weitere Informationen finden Sie auf [SUPPORT_SITE]."/> <check_box label="Gruppenzugang erlauben: [GROUP]" name="GroupCheck" tool_tip="Gruppe im Register „Allgemein“ festlegen."/> <check_box label="Pässe verkaufen an:" name="PassCheck" tool_tip="Ermöglicht befristeten Zugang zu dieser Parzelle"/> <combo_box name="pass_combo"> diff --git a/indra/newview/skins/default/xui/de/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/de/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..3dc554b120 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_animation_anim_preview.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Anim Preview" title="ANIMATION.ANIM"> + <text name="name_label"> + Name: + </text> + <text name="description_label"> + Beschreibung: + </text> + <button label="Hochladen (L$ [AMOUNT])" name="ok_btn"/> + <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_animation_bvh_preview.xml b/indra/newview/skins/default/xui/de/floater_animation_bvh_preview.xml new file mode 100644 index 0000000000..9a6f5e0166 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_animation_bvh_preview.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Animation Preview"> + <floater.string name="failed_to_initialize"> + Bewegung konnte nicht initialisiert werden + </floater.string> + <floater.string name="anim_too_long"> + Animationsdatei ist [LENGTH] Sekunden lang. + +Maximal erlaubt sind [MAX_LENGTH] Sekunden. + </floater.string> + <floater.string name="failed_file_read"> + Animationsdatei kann nicht gelesen werden. + +[STATUS] + </floater.string> + <floater.string name="E_ST_OK"> + OK + </floater.string> + <floater.string name="E_ST_EOF"> + Vorzeitiges Dateiende. + </floater.string> + <floater.string name="E_ST_NO_CONSTRAINT"> + Constraint-Definition kann nicht gelesen werden. + </floater.string> + <floater.string name="E_ST_NO_FILE"> + BVH-Datei kann nicht geöffnet werden. + </floater.string> + <floater.string name="E_ST_NO_HIER"> + Ungültige HIERARCHY-Kopfzeile. + </floater.string> + <floater.string name="E_ST_NO_JOINT"> + ROOT oder JOINT nicht gefunden. + </floater.string> + <floater.string name="E_ST_NO_NAME"> + JOINT-Name nicht erfasst. + </floater.string> + <floater.string name="E_ST_NO_OFFSET"> + OFFSET nicht gefunden. + </floater.string> + <floater.string name="E_ST_NO_CHANNELS"> + CHANNELS nicht gefunden. + </floater.string> + <floater.string name="E_ST_NO_ROTATION"> + Rotationsreihenfolge kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_AXIS"> + Rotationsachse kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_MOTION"> + MOTION nicht gefunden. + </floater.string> + <floater.string name="E_ST_NO_FRAMES"> + Anzahl der Bilder kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_FRAME_TIME"> + Bildzeit kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_POS"> + Positionswerte können nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_ROT"> + Rotationswerte können nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_FILE"> + Transformationsdatei kann nicht geöffnet werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_HEADER"> + Transformationskopfzeile kann nicht gelesen werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_NAME"> + Transformationsnamen können nicht gelesen werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_IGNORE"> + Ignorieren-Transformationswert kann nicht gelesen werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_RELATIVE"> + Relativer Transformationswert kann nicht gelesen werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_OUTNAME"> + Outname-Transformationswert kann nicht gelesen werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_MATRIX"> + Transformationsmatrix kann nicht gelesen werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGECHILD"> + Mergechild-Name kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGEPARENT"> + Mergeparent-Name kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_PRIORITY"> + Priority-Wert kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_LOOP"> + Loop-Wert kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEIN"> + EaseIn-Werte können nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEOUT"> + EaseOut-Werte können nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_HAND"> + Hand-Morph-Wert kann nicht erfasst werden. + </floater.string> + <floater.string name="E_ST_NO_XLT_EMOTE"> + Emote-Name kann nicht gelesen werden. + </floater.string> + <floater.string name="E_ST_BAD_ROOT"> + Falscher Root-Joint-Name, „hip“ verwenden. + </floater.string> + <text name="name_label"> + Name: + </text> + <text name="description_label"> + Beschreibung: + </text> + <spinner label="Priorität" name="priority" tool_tip="Steuert, welche Animationen von dieser Animation überschrieben werden können"/> + <check_box label="Schleife" name="loop_check" tool_tip="Erzeugt eine Animationsschleife"/> + <spinner label="Ein (%)" name="loop_in_point" tool_tip="Anfang einer Animationsschleife festlegen"/> + <spinner label="Aus (%)" name="loop_out_point" tool_tip="Ende einer Animationsschleife festlegen"/> + <text name="hand_label"> + Handhaltung + </text> + <combo_box name="hand_pose_combo" tool_tip="Steuert während der Animation die Bewegung der Hände"> + <combo_box.item label="Dehnen" name="Spread"/> + <combo_box.item label="Entspannt" name="Relaxed"/> + <combo_box.item label="Beide zeigen" name="PointBoth"/> + <combo_box.item label="Faust" name="Fist"/> + <combo_box.item label="Links entspannt" name="RelaxedLeft"/> + <combo_box.item label="Nach links zeigen" name="PointLeft"/> + <combo_box.item label="Linke Faust" name="FistLeft"/> + <combo_box.item label="Rechts entspannt" name="RelaxedRight"/> + <combo_box.item label="Nach rechts zeigen" name="PointRight"/> + <combo_box.item label="Rechte Faust" name="FistRight"/> + <combo_box.item label="Rechts salutieren" name="SaluteRight"/> + <combo_box.item label="Tippen" name="Typing"/> + <combo_box.item label="Friedensgeste rechts" name="PeaceRight"/> + </combo_box> + <text name="emote_label"> + Ausdruck + </text> + <combo_box name="emote_combo" tool_tip="Steuert Gesichtsregungen während der Animation"> + <item label="(Keine)" name="[None]" value=""/> + <item label="Aaaaah" name="Aaaaah" value="Aaaaah"/> + <item label="Ängstlich" name="Afraid" value="Ängstlich"/> + <item label="Verärgert" name="Angry" value="Verärgert"/> + <item label="Grinst" name="BigSmile" value="Grinst"/> + <item label="Gelangweilt" name="Bored" value="Gelangweilt"/> + <item label="Weinen" name="Cry" value="Weinen"/> + <item label="Verachtung" name="Disdain" value="Verachtung"/> + <item label="Verlegen" name="Embarrassed" value="Verlegen"/> + <item label="Stirnrunzeln" name="Frown" value="Stirnrunzeln"/> + <item label="Küssen" name="Kiss" value="Küssen"/> + <item label="Lachen" name="Laugh" value="Lachen"/> + <item label="Bäääh" name="Plllppt" value="Bäääh"/> + <item label="Angewidert" name="Repulsed" value="Angewidert"/> + <item label="Traurig" name="Sad" value="Traurig"/> + <item label="Achselzucken" name="Shrug" value="Achselzucken"/> + <item label="Lächeln" name="Smile" value="Lächeln"/> + <item label="Ãœberraschung" name="Surprise" value="Ãœberraschung"/> + <item label="Zwinkern" name="Wink" value="Zwinkern"/> + <item label="Sorgenvoll" name="Worry" value="Sorgenvoll"/> + </combo_box> + <text name="preview_label"> + Vorschau während: + </text> + <combo_box name="preview_base_anim" tool_tip="Hiermit können Sie das Verhalten Ihres Avatars testen, während Ihr Avatar normale Bewegungen ausführt."> + <item label="Stehen" name="Standing" value="Stehen"/> + <item label="Gehen" name="Walking" value="Gehen"/> + <item label="Sitzen" name="Sitting" value="Sitzen"/> + <item label="Fliegen" name="Flying" value="Fliegen"/> + </combo_box> + <spinner label="Einblenden (s)" name="ease_in_time" tool_tip="Einblendungszeit für Animationen (in Sekunden)"/> + <spinner label="Ausblenden (s)" name="ease_out_time" tool_tip="Ausblendungszeit für Animationen (in Sekunden)"/> + <button name="play_btn" tool_tip="Animation abspielen"/> + <button name="pause_btn" tool_tip="Animation unterbrechen"/> + <button name="stop_btn" tool_tip="Animation anhalten"/> + <text name="bad_animation_text"> + Animationsdatei kann nicht gelesen werden. + +Wir empfehlen exportierte BVH-Dateien aus Poser 4. + </text> + <button label="Hochladen (L$ [AMOUNT])" name="ok_btn"/> + <button label="Abbrechen" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/de/floater_merchant_outbox.xml new file mode 100644 index 0000000000..a412b530a4 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_merchant_outbox.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_merchant_outbox" title="HÄNDLER-OUTBOX"> + <string name="OutboxFolderCount1"> + 1 Ordner + </string> + <string name="OutboxFolderCountN"> + [NUM] Ordner + </string> + <string name="OutboxImporting"> + Ordner übertragen... + </string> + <string name="OutboxInitializing"> + Initialisieren... + </string> + <panel label=""> + <panel> + <panel name="outbox_inventory_placeholder_panel"> + <text name="outbox_inventory_placeholder_title"> + Laden... + </text> + </panel> + </panel> + <panel> + <button label="In Marktplatz übertragen" name="outbox_import_btn" tool_tip="In meinen Marktplatz-Laden verschieben"/> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_model_wizard.xml b/indra/newview/skins/default/xui/de/floater_model_wizard.xml deleted file mode 100644 index a90f36f202..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="header_panel"> - <text name="header_text"> - Modelldatei auswählen - </text> - </panel> - <panel name="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="header_panel"> - <text name="header_text"> - Modell optimieren - </text> - </panel> - <text name="description"> - Wir haben das Modell auf Leistung optimiert. Sie können es bei Bedarf weiter anpassen. - </text> - <panel name="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="header_panel"> - <text name="header_text"> - Physik anpassen - </text> - </panel> - <text name="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="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="header_panel"> - <text name="header_text"> - Ãœberprüfen - </text> - </panel> - <panel name="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 [FEE] L$ 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="header_panel"> - <text name="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_preview_animation.xml b/indra/newview/skins/default/xui/de/floater_preview_animation.xml index 3dcdb52555..2dd47a27ad 100644 --- a/indra/newview/skins/default/xui/de/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/de/floater_preview_animation.xml @@ -7,6 +7,6 @@ Beschreibung: </text> <line_editor left="108" name="desc" width="160"/> - <button label="Inworld abspielen" label_selected="Stopp" name="Anim play btn" tool_tip="Diese Animation so wiedergeben, dass andere sie sehen können." width="116"/> - <button label="Lokal abspielen" label_selected="Stopp" left="171" name="Anim audition btn" tool_tip="Diese Animation so wiedergeben, dass nur Sie sie sehen." width="116"/> + <button label="Inworld abspielen" label_selected="Stopp" name="Inworld" tool_tip="Diese Animation so wiedergeben, dass andere sie sehen können."/> + <button label="Lokal wiedergeben" label_selected="Stopp" name="Locally" tool_tip="Diese Animation so wiedergeben, dass nur Sie sie sehen."/> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/de/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..429447c378 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_test_layout_stacks.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="LAYOUTSTACK-TESTS"/> diff --git a/indra/newview/skins/default/xui/de/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/de/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..506d2b013a --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_test_text_vertical_aligment.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="TEST-FENSTER"/> diff --git a/indra/newview/skins/default/xui/de/floater_tools.xml b/indra/newview/skins/default/xui/de/floater_tools.xml index cf1d03f32d..dee89b28e5 100644 --- a/indra/newview/skins/default/xui/de/floater_tools.xml +++ b/indra/newview/skins/default/xui/de/floater_tools.xml @@ -1,5 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="toolbox floater" short_title="BAU-WERKZEUGE" title=""> + <floater.string name="grid_screen_text"> + Bildschirm + </floater.string> + <floater.string name="grid_local_text"> + Lokal + </floater.string> + <floater.string name="grid_world_text"> + Welt + </floater.string> + <floater.string name="grid_reference_text"> + Referenz + </floater.string> + <floater.string name="grid_attachment_text"> + Anhang + </floater.string> <floater.string name="status_rotate"> An den farbigen Bändern ziehen, um das Objekt zu drehen </floater.string> @@ -63,7 +78,12 @@ </text> <check_box initial_value="true" label="Texturen dehnen" name="checkbox stretch textures" top_pad="-5"/> <check_box initial_value="true" label="Einrasten" name="checkbox snap to grid" top_pad="15"/> - <button label="Optionen..." label_selected="Optionen..." name="Options..." tool_tip="Mehr Raster-Optionen anzeigen"/> + <combo_box name="combobox grid mode" tool_tip="Wählen Sie das gewünschte Rasterlineal zum Positionieren des Objekts aus."> + <combo_box.item label="Welt" name="World"/> + <combo_box.item label="Lokal" name="Local"/> + <combo_box.item label="Referenz" name="Reference"/> + </combo_box> + <button label="" label_selected="Optionen..." name="Options..." tool_tip="Mehr Raster-Optionen anzeigen"/> <button label="" label_selected="" name="ToolCube" tool_tip="Würfel"/> <button label="" label_selected="" name="ToolPrism" tool_tip="Prisma"/> <button label="" label_selected="" name="ToolPyramid" tool_tip="Pyramide"/> diff --git a/indra/newview/skins/default/xui/de/floater_voice_effect.xml b/indra/newview/skins/default/xui/de/floater_voice_effect.xml index 3dc0fc2322..413a46525c 100644 --- a/indra/newview/skins/default/xui/de/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/de/floater_voice_effect.xml @@ -42,13 +42,16 @@ <string name="effect_Demon"> Dämon </string> + <string name="effect_Female Elf"> + Weibliche Elfe + </string> <string name="effect_Flirty"> Kokett </string> <string name="effect_Foxy"> Attraktiv </string> - <string name="effect_Halloween_2010_Bonus"> + <string name="effect_Halloween 2010 Bonus"> Bonus_Halloween_2010 </string> <string name="effect_Helium"> @@ -57,9 +60,18 @@ <string name="effect_Husky"> Rauchig </string> + <string name="effect_Husky Whisper"> + Rauchiges Flüstern + </string> <string name="effect_Intercom"> Intercom </string> + <string name="effect_Julia"> + Julia + </string> + <string name="effect_Lo Lilt"> + Leises Trällern + </string> <string name="effect_Macho"> Macho </string> @@ -69,6 +81,9 @@ <string name="effect_Mini"> Mini </string> + <string name="effect_Model"> + Modell + </string> <string name="effect_Nano"> Nano </string> @@ -90,6 +105,9 @@ <string name="effect_Roxanne"> Roxanne </string> + <string name="effect_Rumble"> + Rumpeln + </string> <string name="effect_Sabrina"> Sabrina </string> @@ -102,6 +120,9 @@ <string name="effect_Shorty"> Shorty </string> + <string name="effect_Smaller"> + Kleiner + </string> <string name="effect_Sneaky"> Hinterhältig </string> diff --git a/indra/newview/skins/default/xui/de/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/de/menu_inspect_object_gear.xml index 7c47913e30..73e0029b76 100644 --- a/indra/newview/skins/default/xui/de/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/de/menu_inspect_object_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<menu name="Gear Menu"> +<toggleable_menu name="Gear Menu"> <menu_item_call label="Berühren" name="touch"/> <menu_item_call label="Sitzen" name="sit"/> <menu_item_call label="Bezahlen" name="pay"/> @@ -12,7 +12,8 @@ <menu_item_call label="Hinzufügen" name="add"/> <menu_item_call label="Melden" name="report"/> <menu_item_call label="Ignorieren" name="block"/> + <menu_item_call label="Freischalten" name="unblock"/> <menu_item_call label="Hineinzoomen" name="zoom_in"/> <menu_item_call label="Entfernen" name="remove"/> <menu_item_call label="Weitere Infos" name="more_info"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/de/menu_inventory.xml b/indra/newview/skins/default/xui/de/menu_inventory.xml index 733a0b85c3..39b3099336 100644 --- a/indra/newview/skins/default/xui/de/menu_inventory.xml +++ b/indra/newview/skins/default/xui/de/menu_inventory.xml @@ -59,6 +59,7 @@ <menu_item_call label="Eigenschaften" name="Properties"/> <menu_item_call label="Umbenennen" name="Rename"/> <menu_item_call label="Asset-UUID kopieren" name="Copy Asset UUID"/> + <menu_item_call label="Ausschneiden" name="Cut"/> <menu_item_call label="Kopieren" name="Copy"/> <menu_item_call label="Einfügen" name="Paste"/> <menu_item_call label="Als Link einfügen" name="Paste As Link"/> @@ -84,6 +85,6 @@ <menu_item_call label="Hinzufügen" name="Wearable Add"/> <menu_item_call label="Ausziehen" name="Take Off"/> <menu_item_call label="In Händler-Outbox kopieren" name="Merchant Copy"/> - <menu_item_call label="In Händler-Outbox verschieben" name="Merchant Move"/> + <menu_item_call label="In Marktplatz übertragen" name="Marketplace Send"/> <menu_item_call label="--keine Optionen--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/de/menu_login.xml b/indra/newview/skins/default/xui/de/menu_login.xml index c90205fbe4..b43b41a5dc 100644 --- a/indra/newview/skins/default/xui/de/menu_login.xml +++ b/indra/newview/skins/default/xui/de/menu_login.xml @@ -17,8 +17,8 @@ <menu_item_call label="Fenstergröße einstellen..." name="Set Window Size..."/> <menu_item_call label="Servicebedingungen anzeigen" name="TOS"/> <menu_item_call label="Wichtige Meldung anzeigen" name="Critical"/> - <menu_item_call label="Test Medienbrowser" name="Web Browser Test"/> <menu_item_call label="Web Content Floater Debug Test" name="Web Content Floater Debug Test"/> + <menu label="Protokollierungsstufe festlegen" name="Set Logging Level"/> <menu_item_check label="Grid-Auswahl anzeigen" name="Show Grid Picker"/> <menu_item_call label="Benachrichtigungs-Konsole anzeigen" name="Show Notifications Console"/> </menu> diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml index a81874bee9..d011c7295c 100644 --- a/indra/newview/skins/default/xui/de/menu_viewer.xml +++ b/indra/newview/skins/default/xui/de/menu_viewer.xml @@ -14,14 +14,14 @@ <menu_item_check label="Fliegen" name="Fly"/> <menu_item_check label="Immer rennen" name="Always Run"/> <menu_item_call label="Animation meines Avatars stoppen" name="Stop Animating My Avatar"/> + <menu_item_call label="Gehen/Rennen/Fliegen..." name="Walk / run / fly"/> </menu> <menu label="Status" name="Status"> <menu_item_call label="Abwesend" name="Set Away"/> <menu_item_call label="Beschäftigt" name="Set Busy"/> </menu> - <menu_item_call label="Admin-Status anfordern" name="Request Admin Options"/> - <menu_item_call label="Admin-Status verlassen" name="Leave Admin Options"/> - <menu_item_call label="L$ kaufen" name="Buy and Sell L$"/> + <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> @@ -63,7 +63,7 @@ <menu_item_check label="Parzelleneigenschaften" name="Parcel Properties"/> <menu_item_check label="Menü „Erweitert“" name="Show Advanced Menu"/> </menu> - <menu label="Sonne" name="Environment Settings"> + <menu label="Sonne" name="Sun"> <menu_item_call label="Sonnenaufgang" name="Sunrise"/> <menu_item_call label="Mittag" name="Noon"/> <menu_item_call label="Sonnenuntergang" name="Sunset"/> @@ -178,22 +178,22 @@ <menu_item_check label="Fadenkreuz für Mouselook anzeigen" name="ShowCrosshairs"/> </menu> <menu label="Darstellungstypen" name="Rendering Types"> - <menu_item_check label="Einfach" name="Simple"/> - <menu_item_check label="Alpha" name="Alpha"/> - <menu_item_check label="Baum" name="Tree"/> - <menu_item_check label="Avatare" name="Character"/> - <menu_item_check label="Flächenpatch" name="Surface Patch"/> - <menu_item_check label="Himmel" name="Sky"/> - <menu_item_check label="Wasser" name="Water"/> - <menu_item_check label="Boden" name="Ground"/> - <menu_item_check label="Volumen" name="Volume"/> - <menu_item_check label="Gras" name="Grass"/> - <menu_item_check label="Wolken" name="Clouds"/> - <menu_item_check label="Partikel" name="Particles"/> - <menu_item_check label="Unebenheiten" name="Bump"/> + <menu_item_check label="Einfach" name="Rendering Type Simple"/> + <menu_item_check label="Alpha" name="Rendering Type Alpha"/> + <menu_item_check label="Baum" name="Rendering Type Tree"/> + <menu_item_check label="Avatare" name="Rendering Type Character"/> + <menu_item_check label="Flächenpatch" name="Rendering Type Surface Patch"/> + <menu_item_check label="Himmel" name="Rendering Type Sky"/> + <menu_item_check label="Wasser" name="Rendering Type Water"/> + <menu_item_check label="Boden" name="Rendering Type Ground"/> + <menu_item_check label="Volumen" name="Rendering Type Volume"/> + <menu_item_check label="Gras" name="Rendering Type Grass"/> + <menu_item_check label="Wolken" name="Rendering Type Clouds"/> + <menu_item_check label="Partikel" name="Rendering Type Particles"/> + <menu_item_check label="Unebenheiten" name="Rendering Type Bump"/> </menu> <menu label="Rendering-Eigenschaften" name="Rendering Features"> - <menu_item_check label="UI" name="UI"/> + <menu_item_check label="UI" name="ToggleUI"/> <menu_item_check label="Ausgewählt" name="Selected"/> <menu_item_check label="Farblich hervorgehoben" name="Highlighted"/> <menu_item_check label="Dynamische Texturen" name="Dynamic Textures"/> @@ -207,8 +207,6 @@ <menu_item_check label="Weiche Mausbewegung" name="Mouse Smoothing"/> <menu_item_call label="Tasten freigeben" name="Release Keys"/> <menu label="Tastaturkürzel" name="Shortcuts"> - <menu_item_call label="Bild ([COST] L$)..." name="Upload Image"/> - <menu_item_check label="Suchen" name="Search"/> <menu_item_check label="Erweitert-Menü anzeigen - veraltetet" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Fenster schließen" name="Close Window"/> <menu_item_call label="Alle Fenster schließen" name="Close All Windows"/> @@ -217,13 +215,6 @@ <menu_item_check label="Joystick-Flycam" name="Joystick Flycam"/> <menu_item_call label="Ansicht zurücksetzen" name="Reset View"/> <menu_item_call label="Letzten Chatter ansehen" name="Look at Last Chatter"/> - <menu label="Bauwerkzeug auswählen" name="Select Tool"> - <menu_item_call label="Fokus-Werkzeug" name="Focus"/> - <menu_item_call label="Werkzeug „Bewegen“" name="Move"/> - <menu_item_call label="Bearbeiten" name="Edit"/> - <menu_item_call label="Werkzeug „Erstellen"" name="Create"/> - <menu_item_call label="Land-Werkzeug" name="Land"/> - </menu> <menu_item_call label="Hineinzoomen" name="Zoom In"/> <menu_item_call label="Zoom-Standard" name="Zoom Default"/> <menu_item_call label="Wegzoomen" name="Zoom Out"/> @@ -296,6 +287,7 @@ <menu_item_check label="Raycast" name="Raycast"/> <menu_item_check label="Windvektoren" name="Wind Vectors"/> <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> <menu label="Rendering" name="Rendering"> @@ -337,9 +329,8 @@ <menu_item_call label="Aufnahme starten" name="Start Record"/> <menu_item_call label="Aufnahme stoppen" name="Stop Record"/> </menu> - <menu label="Welt" name="World"> + <menu label="Welt" name="DevelopWorld"> <menu_item_check label="Sonnen-Override für Sim" name="Sim Sun Override"/> - <menu_item_check label="Pulsierender Strahl" name="Cheesy Beacon"/> <menu_item_check label="Festgelegtes Wetter" name="Fixed Weather"/> <menu_item_call label="Regionsobjekt-Cache ausgeben" name="Dump Region Object Cache"/> </menu> @@ -371,11 +362,11 @@ </menu> <menu label="Avatar" name="Character"> <menu label="Geladene Textur nehmen" name="Grab Baked Texture"> - <menu_item_call label="Iris" name="Iris"/> - <menu_item_call label="Kopf" name="Head"/> - <menu_item_call label="Oberkörper" name="Upper Body"/> - <menu_item_call label="Unterkörper" name="Lower Body"/> - <menu_item_call label="Rock" name="Skirt"/> + <menu_item_call label="Iris" name="Grab Iris"/> + <menu_item_call label="Kopf" name="Grab Head"/> + <menu_item_call label="Oberkörper" name="Grab Upper Body"/> + <menu_item_call label="Unterkörper" name="Grab Lower Body"/> + <menu_item_call label="Rock" name="Grab Skirt"/> </menu> <menu label="Avatar-Tests" name="Character Tests"> <menu_item_call label="Aussehen als XML speichern" name="Appearance To XML"/> @@ -403,20 +394,28 @@ <menu_item_check label="HTTP-Texturen" name="HTTP Textures"/> <menu_item_check label="HTTP-Inventar" name="HTTP Inventory"/> <menu_item_call label="Bilder komprimieren" name="Compress Images"/> + <menu_item_call label="Visual Leak Detector aktivieren" name="Enable Visual Leak Detector"/> <menu_item_check label="Ausgabe Fehlerbeseitigung ausgeben" name="Output Debug Minidump"/> <menu_item_check label="Bei nächster Ausführung Fenster öffnen" name="Console Window"/> + <menu label="Protokollierungsstufe festlegen" name="Set Logging Level"> + <menu_item_check label="Debug" name="Debug"/> + <menu_item_check label="Info" name="Info"/> + <menu_item_check label="Warnung" name="Warning"/> + <menu_item_check label="Fehler" name="Error"/> + <menu_item_check label="Keine" name="None"/> + </menu> <menu_item_call label="Admin-Status anfordern" name="Request Admin Options"/> <menu_item_call label="Admin-Status verlassen" name="Leave Admin Options"/> <menu_item_check label="Admin-Menü anzeigen" name="View Admin Options"/> </menu> <menu label="Admin" name="Admin"> - <menu label="Object"> - <menu_item_call label="Kopie nehmen" name="Take Copy"/> - <menu_item_call label="Besitzer zu mir zwingen" name="Force Owner To Me"/> - <menu_item_call label="Erlaubnis des Besitzers erzwingen" name="Force Owner Permissive"/> + <menu label="Objekt" name="AdminObject"> + <menu_item_call label="Kopie nehmen" name="Admin Take Copy"/> + <menu_item_call label="Mich zum Besitzer machen" name="Force Owner To Me"/> + <menu_item_call label="Besitzererlaubnis erzwingen" name="Force Owner Permissive"/> <menu_item_call label="Löschen" name="Delete"/> - <menu_item_call label="Fest" name="Lock"/> - <menu_item_call label="Asset-ID zulassen" name="Get Assets IDs"/> + <menu_item_call label="Sperren" name="Lock"/> + <menu_item_call label="Asset-IDs abrufen" name="Get Assets IDs"/> </menu> <menu label="Parzelle" name="Parcel"> <menu_item_call label="Besitzer zu mir zwingen" name="Owner To Me"/> @@ -447,14 +446,14 @@ <menu_item_call label="Physik" name="Physics"/> <menu_item_call label="Alle Kleider" name="All Clothes"/> </menu> - <menu label="Hilfe" name="Help"> + <menu label="Hilfe" name="DeprecatedHelp"> <menu_item_call label="Offizielles Linden-Blog" name="Official Linden Blog"/> <menu_item_call label="Scripting-Portal" name="Scripting Portal"/> <menu label="Fehlermeldungen" name="Bug Reporting"> <menu_item_call label="Allgemeiner Probleme-Tracker" name="Public Issue Tracker"/> <menu_item_call label="Hilfe zum Allgemeinen Probleme-Tracker" name="Publc Issue Tracker Help"/> <menu_item_call label="Fehlermeldungs-1x1" name="Bug Reporing 101"/> - <menu_item_call label="Sicherheitsfragen" name="Security Issues"/> + <menu_item_call label="Sicherheitsprobleme" name="Security Issues"/> <menu_item_call label="QA-Wiki" name="QA Wiki"/> </menu> </menu> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index a34b938a7a..ac068fcd4e 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -86,17 +86,38 @@ Stellen Sie sicher, dass Ihre Internetverbindung funktioniert. <usetemplate canceltext="Abbrechen" name="yesnocancelbuttons" notext="Nicht speichern" yestext="Speichern"/> </notification> <notification name="ConfirmNoCopyToOutbox"> - Ihnen fehlt die Berechtigung zum Kopieren dieses Artikels in die Händler-Outbox. Möchten Sie wirklich den folgenden Artikel verschieben? - [ITEM_NAME] - <usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/> + Sie sind nicht berechtigt, einen oder mehrere dieser Artikel in die Händler-Outbox zu kopieren. Sie können sie verschieben oder zurücklassen. + <usetemplate name="okcancelbuttons" notext="Artikel nicht verschieben" yestext="Artikel verschieben"/> + </notification> + <notification name="OutboxFolderCreated"> + Für jeden Artikel, den Sie in die oberste Ebene Ihrer Händler-Outbox übertragen haben, wurde ein neuer Ordner erstellt. + <usetemplate ignoretext="Neuer Ordner in Händler-Outbox erstellt" name="okignore" yestext="OK"/> </notification> - <notification name="OutboxUploadComplete"> - Marktplatz-Upload abgeschlossen. - <usetemplate name="okbutton" yestext="Hurra!"/> + <notification name="OutboxImportComplete"> + Erfolg + +Alle Ordner wurden erfolgreich an den Marktplatz übertragen. + <usetemplate ignoretext="Alle Ordner an den Marktplatz übertragen" name="okignore" yestext="OK"/> </notification> - <notification name="OutboxUploadHadErrors"> - Marktplatz-Upload mit Fehlern abgeschlossen. Korrigieren Sie die Fehler in Ihrer Outbox und versuchen Sie es erneut. Vielen Dank! - <usetemplate name="okbutton" yestext="Erneut versuchen"/> + <notification name="OutboxImportHadErrors"> + Einige Ordner wurden nicht übertragen + +Beim Ãœbertragen bestimmter Ordner an den Marktplatz ist ein Fehler aufgetreten. Diese Ordner befinden sich noch in Ihrer Händler-Outbox. + +Weitere Informationen finden Sie im [[MARKETPLACE_IMPORTS_URL] Fehlerprotokoll]. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxImportFailed"> + Ãœbertragung fehlgeschlagen + +Aufgrund eines System- oder Netzwerkfehlers wurden keine Ordner an den Marktplatz übertragen. Versuchen Sie es später erneut. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxInitFailed"> + Marktplatzinitialisierung fehlgeschlagen + +Marktplatzinitialisierung aufgrund eines System- oder Netzwerkfehlers fehlgeschlagen. Versuchen Sie es später erneut. + <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="CompileQueueSaveText"> Der Text für ein Skript konnte aus folgendem Grund nicht hochgeladen werden: [REASON]. Bitte versuchen Sie es erneut. @@ -656,7 +677,7 @@ Erwartet wurde [VALIDS] Ausgabedatei konnte nicht erstellt werden: [FILE] </notification> <notification name="DoNotSupportBulkAnimationUpload"> - Der Mehrfach-Upload von Animationsdateien wird zurzeit von [APP_NAME] nicht unterstützt. + Der Bulk-Upload von BVH-Animationsdateien wird zurzeit von [APP_NAME] nicht unterstützt. </notification> <notification name="CannotUploadReason"> Datei [FILE] kann aus folgendem Grund nicht hochgeladen werden: [REASON] @@ -1448,7 +1469,7 @@ Zur Installation des Updates muss [APP_NAME] neu gestartet werden. <usetemplate ignoretext="Bestätigen, bevor Objekte an Ihre Eigentümer zurückgegeben werden" name="okcancelignore" notext="Abbrechen" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Sie sind Mitglied der Gruppe <nolink>[GROUP]</nolink>. + Sie sind gegenwärtig Mitglied der Gruppe <nolink>[GROUP]</nolink>. Diese Gruppe verlassen? <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> </notification> @@ -2623,16 +2644,16 @@ Anfrage gestatten? „<nolink>[TITLE]</nolink>“ von [NAME] [MESSAGE] <form name="form"> - <button name="Mute" text="Blockieren"/> - <button name="Ignore" text="Ignorieren"/> + <button name="Client_Side_Mute" text="Blockieren"/> + <button name="Client_Side_Ignore" text="Ignorieren"/> </form> </notification> <notification name="ScriptDialogGroup"> „<nolink>[TITLE]</nolink>“ von [GROUPNAME] [MESSAGE] <form name="form"> - <button name="Mute" text="Blockieren"/> - <button name="Ignore" text="Ignorieren"/> + <button name="Client_Side_Mute" text="Blockieren"/> + <button name="Client_Side_Ignore" text="Ignorieren"/> </form> </notification> <notification name="BuyLindenDollarSuccess"> @@ -2831,6 +2852,18 @@ für folgende Einwohner freigeben: [RESIDENTS] <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> </notification> + <notification name="ShareFolderConfirmation"> + Es kann nur jeweils ein Ordner geteilt werden. + +Möchten Sie wirklich die folgenden Artikel: + +<nolink>[ITEMS]</nolink> + +mit den folgenden Einwohnern teilen: + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> + </notification> <notification name="ItemsShared"> Objekte wurden erfolgreich freigegeben. </notification> diff --git a/indra/newview/skins/default/xui/de/panel_nearby_chat.xml b/indra/newview/skins/default/xui/de/panel_nearby_chat.xml index 2068c39024..07ad761791 100644 --- a/indra/newview/skins/default/xui/de/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/de/panel_nearby_chat.xml @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="nearby_chat"> - <check_box label="Chat übersetzen" name="translate_chat_checkbox"/> + <layout_stack name="stack"> + <layout_panel name="translate_chat_checkbox_lp"> + <check_box label="Chat übersetzen" name="translate_chat_checkbox"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/de/panel_region_estate.xml b/indra/newview/skins/default/xui/de/panel_region_estate.xml index b93bd3e442..aecf6f62fc 100644 --- a/indra/newview/skins/default/xui/de/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/de/panel_region_estate.xml @@ -16,10 +16,10 @@ (unbekannt) </text> <text name="Only Allow"> - Zugang nur dann, wenn überprüft mit: + Zugang nur Einwohnern gestatten, die: </text> - <check_box label="Zahlungsinformation gespeichert" name="limit_payment" tool_tip="Einwohner ohne Zahlungsinformation nicht zulassen."/> - <check_box label="Altersüberprüfung" name="limit_age_verified" tool_tip="Einwohner ohne Altersüberprüfung verbannen. Weitere Informationen finden Sie auf [SUPPORT_SITE]."/> + <check_box label="Zahlungsinformationen hinterlegt haben" name="limit_payment" tool_tip="Um diesen Grundbesitz besuchen zu können, müssen Einwohner Zahlungsinformationen hinterlegt haben. Weitere Informationen finden Sie auf [SUPPORT_SITE]."/> + <check_box label="ihr Alter bestätigt haben" name="limit_age_verified" tool_tip="Um diesen Grundbesitz besuchen zu können, müssen Einwohner ihr Alter bestätigt haben. Weitere Informationen finden Sie auf [SUPPORT_SITE]."/> <check_box label="Voice-Chat erlauben" name="voice_chat_check"/> <button label="?" name="voice_chat_help"/> <text name="abuse_email_text" width="222"> diff --git a/indra/newview/skins/default/xui/de/panel_script_ed.xml b/indra/newview/skins/default/xui/de/panel_script_ed.xml index adfe2a342b..7e03aeff15 100644 --- a/indra/newview/skins/default/xui/de/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/de/panel_script_ed.xml @@ -22,6 +22,8 @@ <menu label="Datei" name="File"> <menu_item_call label="Speichern" name="Save"/> <menu_item_call label="Alle Änderungen zurücksetzen" name="Revert All Changes"/> + <menu_item_call label="Aus Datei laden..." name="LoadFromFile"/> + <menu_item_call label="In Datei speichern..." name="SaveToFile"/> </menu> <menu label="Bearbeiten" name="Edit"> <menu_item_call label="Rückgängig" name="Undo"/> diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml index 2493d60df6..14ace0ac3a 100644 --- a/indra/newview/skins/default/xui/de/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml @@ -15,7 +15,7 @@ <panel.string name="buycurrencylabel"> [AMT] L$ </panel.string> - <panel name="balance_bg"> + <panel left="-415" name="balance_bg" width="205"> <text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="20 L$"/> <button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/> <button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen" width="85"/> diff --git a/indra/newview/skins/default/xui/de/sidepanel_inventory.xml b/indra/newview/skins/default/xui/de/sidepanel_inventory.xml index 674ea3376b..18aad64f96 100644 --- a/indra/newview/skins/default/xui/de/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/de/sidepanel_inventory.xml @@ -2,47 +2,24 @@ <panel label="Sonstiges" name="objects panel"> <panel label="" name="sidepanel__inventory_panel"> <layout_stack name="inventory_layout_stack"> - <layout_panel name="inbox_outbox_layout_panel"> - <layout_stack name="inbox_outbox_layout_stack"> - <layout_panel name="inbox_layout_panel"> - <panel label="" name="marketplace_inbox"> - <string name="InboxLabelWithArg"> - Erhaltene Artikel ([NUM]) - </string> - <string name="InboxLabelNoArg"> - Erhaltene Artikel - </string> - <button label="Erhaltene Artikel" name="inbox_btn"/> - <text name="inbox_fresh_new_count"> - [NUM] neu - </text> - <panel tool_tip="Drag and drop items to your inventory to manage and use them"> - <text name="inbox_inventory_placeholder"> - Einkäufe auf dem Marktplatz werden hierher geliefert. - </text> - </panel> - </panel> - </layout_panel> - <layout_panel name="outbox_layout_panel"> - <panel label="" name="marketplace_outbox"> - <string name="OutboxLabelWithArg"> - Händler-Outbox ([NUM]) - </string> - <string name="OutboxLabelNoArg"> - Händler-Outbox - </string> - <button label="Händler-Outbox" name="outbox_btn"/> - <button label="" name="outbox_sync_btn" tool_tip="In meinen Marktplatz-Laden verschieben"/> - <panel> - <panel name="outbox_inventory_placeholder_panel"> - <text name="outbox_inventory_placeholder_title"> - Laden... - </text> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> + <layout_panel name="inbox_layout_panel"> + <panel label="" name="marketplace_inbox"> + <string name="InboxLabelWithArg"> + Erhaltene Artikel ([NUM]) + </string> + <string name="InboxLabelNoArg"> + Erhaltene Artikel + </string> + <button label="Erhaltene Artikel" name="inbox_btn"/> + <text name="inbox_fresh_new_count"> + [NUM] neu + </text> + <panel name="inbox_inventory_placeholder_panel" tool_tip="Artikel zur Verwendung in Ihr Inventar ziehen"> + <text name="inbox_inventory_placeholder"> + Einkäufe aus dem Marktplatz werden hierher geliefert. + </text> + </panel> + </panel> </layout_panel> </layout_stack> <panel name="button_panel"> diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 14e9fcdb7f..d917d33d12 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -181,8 +181,8 @@ Aktuelle Informationen finden Sie unter www.secondlife.com/status. </string> <string name="LoginFailedPremiumOnly"> Die Anmeldung bei Second Life ist vorübergehend eingeschränkt, um sicherzustellen, dass Einwohner, die sich bereits inworld aufhalten, das bestmögliche Erlebnis haben. - -Benutzer mit kostenlosen Konten können sich während dieses Zeitraums nicht bei Second Life anmelden, damit die Kapazität den Benutzern zur Verfügung steht, die ein gebührenpflichtiges Premium-Konto besitzen. + +Benutzer mit kostenlosen Konten können sich während dieses Zeitraums nicht bei Second Life anmelden, damit die Kapazität Benutzern zur Verfügung steht, die ein gebührenpflichtiges Premium-Konto besitzen. </string> <string name="LoginFailedComputerProhibited"> Der Zugriff auf Second Life ist von diesem Computer aus nicht möglich. @@ -339,17 +339,35 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. Sie können nur ein einzelnes Objekt hierher ziehen </string> <string name="TooltipPrice" value="[AMOUNT] L$"/> + <string name="TooltipOutboxDragToWorld"> + Sie können Artikel nicht in Ihrer Händler-Outbox rezzen + </string> <string name="TooltipOutboxNoTransfer"> - Eines oder mehrere dieser Objekte können nicht verkauft oder an einen anderen Benutzer übertragen werden. + Einer oder mehrere dieser Artikel können nicht verkauft oder übertragen werden. + </string> + <string name="TooltipOutboxNotInInventory"> + Nur Artikel direkt aus Ihrem Inventar können in Ihre Händler-Outbox gelegt werden </string> <string name="TooltipOutboxWorn"> - Sie tragen eines oder mehrere dieser Objekte. Nehmen Sie es/sie von Ihrem Avatar ab und versuchen Sie dann erneut, es/sie zu verschieben. + Artikel, die Sie tragen, können nicht in Ihre Händler-Outbox gelegt werden. + </string> + <string name="TooltipOutboxCallingCard"> + Sie können keine Visitenkarten in Ihre Händler-Outbox legen </string> <string name="TooltipOutboxFolderLevels"> - Dieser Ordner hat zu viele Unterordnerebenen. Ordnen Sie die Unterordner so an, dass maximal vier Verschachtelungsebenen vorhanden sind (Stammordner enthält A enthält B enthält C). + Tiefe der verschachtelten Ordner überschreitet 3 + </string> + <string name="TooltipOutboxTooManyFolders"> + Anzahl von Unterordnern im obersten Ordner überschreitet 20 </string> <string name="TooltipOutboxTooManyObjects"> - Dieser Ordner enthält mehr als 200 Objekte. Verpacken Sie einige dieser Artikel in Behältern, um die Anzahl zu verringern. + Anzahl von Artikeln im obersten Ordner überschreitet 200 + </string> + <string name="TooltipDragOntoOwnChild"> + Sie können einen Ordner nicht in einen seiner untergeordneten Ordner verschieben + </string> + <string name="TooltipDragOntoSelf"> + Sie können einen Ordner nicht in sich selbst verschieben </string> <string name="TooltipHttpUrl"> Anklicken, um Webseite anzuzeigen @@ -817,6 +835,9 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="anim_yes_head"> Ja </string> + <string name="multiple_textures"> + Mehrfach + </string> <string name="texture_loading"> Wird geladen... </string> @@ -976,6 +997,9 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="choose_the_directory"> Verzeichnis auswählen </string> + <string name="script_files"> + Skripts + </string> <string name="AvatarSetNotAway"> Nicht abwesend </string> @@ -1214,43 +1238,36 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. Sie haben keine Kopie dieser Textur in Ihrem Inventar. </string> <string name="InventoryInboxNoItems"> - Wenn Sie einen Artikel kaufen oder anderweitig erhalten, erscheint er hier, damit Sie ihn in einen Ordner in Ihrem Inventar ziehen bzw. löschen können, wenn Sie ihn nicht behalten möchten. + Einkäufe aus dem Marktplatz erscheinen hier. Sie können diese dann zur Verwendung in Ihr Inventar ziehen. </string> <string name="MarketplaceURL"> - http://marketplace.[DOMAIN_NAME] + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/ </string> <string name="MarketplaceURL_CreateStore"> - http://marketplace.[DOMAIN_NAME]/create_store + http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 </string> - <string name="MarketplaceURL_LearnMore"> - http://marketplace.[DOMAIN_NAME]/learn_more - </string> - <string name="InventoryOutboxCreationErrorTitle"> - Ihre Händler-Outbox ist nicht richtig konfiguriert + <string name="MarketplaceURL_Dashboard"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard </string> - <string name="InventoryOutboxCreationErrorTooltip"> - Konfigurationsfehler in Händler-Outbox + <string name="MarketplaceURL_Imports"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports </string> - <string name="InventoryOutboxCreationError"> - Wenden Sie sich zur Behebung des Problems an den Kundendienst. + <string name="MarketplaceURL_LearnMore"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more </string> <string name="InventoryOutboxNotMerchantTitle"> - Jeder kann Artikel im Marktplatz verkaufen - </string> - <string name="InventoryOutboxNotMerchantTooltip"> - Werden Sie Händler! + Jeder kann Artikel im Marktplatz verkaufen. </string> + <string name="InventoryOutboxNotMerchantTooltip"/> <string name="InventoryOutboxNotMerchant"> - [[MARKETPLACE_URL] Im Second Life Marktplatz] werden über eine Million virtuelle Produkte zum Verkauf angeboten, die alle von Einwohnern erstellt wurden. Auch Sie können selbst erstellte Artikel sowie bestimmte gekaufte Artikel verkaufen. Die Einrichtung eines Händlerkontos geht blitzschnell und ist kostenlos. [[LEARN_MORE_URL] Lesen Sie weitere Informationen] oder [[CREATE_STORE_URL] öffnen Sie einen Laden] im Marktplatz, um Ihre Objekte zu verkaufen. + Wenn Sie als Händler aktiv werden möchten, müssen Sie einen [[MARKETPLACE_CREATE_STORE_URL] Laden im Marktplatz erstellen]. </string> <string name="InventoryOutboxNoItemsTitle"> - Eine neue Methode, um Artikel in den Marktplatz zu übertragen - </string> - <string name="InventoryOutboxNoItemsTooltip"> - Legen Sie Artikel hier ab, um sie zum Verkauf im Marktplatz vorzubereiten + Ihre Outbox ist leer. </string> + <string name="InventoryOutboxNoItemsTooltip"/> <string name="InventoryOutboxNoItems"> - Ziehen Sie zu verkaufende Artikel oder Ordner in diesen Bereich. Es erscheinen Kopien der Artikel; Ihr Inventar bleibt unverändert, es sei denn, es handelt sich um einen nicht kopierbaren Artikel. Wenn die Artikel in den Marktplatz übertragen werden sollen, klicken Sie auf die Schaltfläche „Hochladen“. Nach Ãœbertragung der Artikel in Ihr Marktplatz-Inventar verschwinden sie aus diesem Ordner. + Ziehen Sie Ordner in dien Bereich und klicken Sie auf „In Marktplatz übertragen“, um sie im [[MARKETPLACE_DASHBOARD_URL] Marktplatz] zum Verkauf anzubieten. </string> <string name="Marketplace Error None"> Keine Fehler @@ -3907,6 +3924,9 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_ <string name="Saved_message"> (Gespeichert am [LONG_TIMESTAMP]) </string> + <string name="IM_unblock_only_groups_friends"> + Wenn Sie diese Meldung sehen, müssen Sie unter „Einstellungen“ > „Privatsphäre“ die Option „Nur IMs und Anrufe von Freunden oder Gruppen durchstellen“ deaktivieren. + </string> <string name="answered_call"> Ihr Anruf wurde entgegengenommen </string> @@ -4103,8 +4123,8 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_ Online </string> <string name="uploading_abuse_report"> - Bericht wird hochgeladen... - + Hochladen... + Missbrauchsbericht </string> <string name="New Shape"> @@ -4372,8 +4392,8 @@ Missbrauchsbericht <string name="server_is_down"> Trotz all unserer Bemühungen ist ein unerwarteter Fehler aufgetreten. - Bitte überprüfen Sie status.secondlifegrid.net, um festzustellen, ob ein Problem besteht. - Falls Sie weiterhin Problem haben, überprüfen Sie bitte Ihre Netzwerk- und Firewalleinstellungen. + Bitte überprüfen Sie status.secondlifegrid.net, um herauszufinden, ob ein Problem besteht. + Falls Sie weiterhin Problem haben, überprüfen Sie bitte Ihre Netzwerk- und Firewalleinstellungen. </string> <string name="dateTimeWeekdaysNames"> Sonntag:Montag:Dienstag:Mittwoch:Donnerstag:Freitag:Samstag @@ -4839,6 +4859,9 @@ Setzen Sie den Editorpfad in Anführungszeichen <string name="Command_Move_Label"> Gehen / Rennen / Fliegen </string> + <string name="Command_Outbox_Label"> + Händler-Outbox + </string> <string name="Command_People_Label"> Leute </string> @@ -4911,6 +4934,9 @@ Setzen Sie den Editorpfad in Anführungszeichen <string name="Command_Move_Tooltip"> Ihren Avatar bewegen </string> + <string name="Command_Outbox_Tooltip"> + Artikel zum Verkauf in den Marktplatz übertragen + </string> <string name="Command_People_Tooltip"> Freunde, Gruppen und Leute in der Nähe </string> diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 930bbaa8cb..d11373ce1d 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - legacy_header_height="18" can_minimize="false" can_tear_off="false" can_resize="true" @@ -16,67 +15,98 @@ save_dock_state="true" save_visibility="true" single_instance="true" - width="320"> - <string name="nudge_parabuild" translate="false">Nudge 1</string> - <string name="test_the_vlt">This string CHANGE2 is extracted.</string> - <string name="testing_eli">Just a test. changes.</string> - <text_editor - parse_urls="true" - bg_readonly_color="ChatHistoryBgColor" - bg_writeable_color="ChatHistoryBgColor" - border_visible="false" - follows="all" - font="SansSerif" - left="1" - top="20" - layout="topleft" - height="260" - name="chat_history" - max_length="200000" - parse_highlights="true" - text_color="ChatHistoryTextColor" - text_readonly_color="ChatHistoryTextColor" - translate="false" - track_end="true" - wrap="true" - width="320"> - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - Really long line that is long enough to wrap once with jyg descenders. - </text_editor> + width="650"> + <text left="0" + follows="left|top|bottom" + top="5" + clip_partial="true" + bottom="-5" + width="100" + valign="top"> +this +is +some +text +that +is +top +aligned</text> + <text left_pad="5" + follows="left|top|bottom" + top="5" + bottom="-5" + clip_partial="true" + width="100" + valign="center"> +this +is +some +text +that +is +center +aligned</text> + <text left_pad="5" + follows="left|top|bottom" + top="5" + clip_partial="true" + bottom="-5" + width="100" + valign="bottom"> +this +is +some +text +that +is +bottom +aligned</text> + <text_editor left_pad="5" + follows="left|top|bottom" + top="5" + clip_partial="true" + bottom="-5" + width="100" + valign="top"> +this +is +some +text +that +is +top +aligned + </text_editor> + <text_editor left_pad="5" + follows="left|top|bottom" + top="5" + bottom="-5" + clip_partial="true" + width="100" + valign="center"> +this +is +some +text +that +is +center +aligned + </text_editor> + <text_editor left_pad="5" + follows="left|top|bottom" + top="5" + clip_partial="true" + bottom="-5" + width="100" + valign="bottom"> +this +is +some +text +that +is +bottom +aligned + </text_editor> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index c7e9ec781d..060d889003 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="centered" + positioning="centered" legacy_header_height="18" height="440" layout="topleft" 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 1d5a6740b7..fb123ec4d1 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.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="420" layout="topleft" @@ -192,12 +192,12 @@ type="string" length="1" follows="left|top" - height="20" + height="18" layout="topleft" left_pad="2" valign="center" name="ContentRatingText" - top_delta="0" + top_delta="-2" width="250"> Adult </text> @@ -209,7 +209,7 @@ layout="topleft" left="10" name="Owner:" - top_pad="1" + top_pad="3" width="100"> Owner: </text> @@ -736,7 +736,7 @@ height="16" layout="topleft" left_pad="10" - top_delta="-3" + top_delta="-1" mouse_opaque="false" name="region_maturity_text" valign="center" @@ -1210,7 +1210,7 @@ Only large parcels can be listed in search. type="string" length="1" follows="left|top" - text_color="white" + text_color="White" height="16" layout="topleft" left="10" @@ -1500,7 +1500,7 @@ Only large parcels can be listed in search. layout="topleft" left="20" name="Snapshot:" - text_color="white" + text_color="White" top="225" width="200"> Snapshot: @@ -1546,7 +1546,7 @@ Only large parcels can be listed in search. layout="topleft" left="255" top="282" - text_color="white" + text_color="White" name="landing_point" word_wrap="true" width="200"> @@ -1576,7 +1576,7 @@ Only large parcels can be listed in search. <text type="string" length="1" - text_color="white" + text_color="White" follows="left|top" height="16" layout="topleft" @@ -1951,7 +1951,7 @@ Only large parcels can be listed in search. name="access_estate_defined"> (Defined by the Estate) </panel.string> - <panel.string + <panel.string name="estate_override"> One or more of these options is set at the estate level </panel.string> @@ -2085,7 +2085,7 @@ Only large parcels can be listed in search. column_padding="0" follows="top|bottom" heading_height="14" - height="120" + height="125" layout="topleft" left="0" multi_select="true" @@ -2134,7 +2134,7 @@ Only large parcels can be listed in search. column_padding="0" follows="top|bottom" heading_height="14" - height="120" + height="125" layout="topleft" left="0" multi_select="true" diff --git a/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..b5538a511c --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + height="190" + layout="topleft" + name="Anim Preview" + help_topic="animation_anim_preview" + title="ANIMATION.ANIM" + width="300"> + <text + type="string" + length="1" + follows="left|top" + height="15" + layout="topleft" + left="10" + mouse_opaque="false" + name="name_label" + top="20" + width="275"> + Name: + </text> + <line_editor + border_style="line" + border_thickness="1" + follows="left|top|right" + height="19" + layout="topleft" + left_delta="0" + max_length_bytes="63" + name="name_form" + top_pad="0" + width="280" /> + <text + type="string" + length="1" + follows="left|top" + height="15" + layout="topleft" + left_delta="0" + mouse_opaque="false" + name="description_label" + top_pad="10" + width="270"> + Description: + </text> + <line_editor + border_style="line" + border_thickness="1" + follows="left|top|right" + height="19" + layout="topleft" + left_delta="0" + max_length_bytes="127" + name="description_form" + top_pad="0" + width="280" /> + <button + follows="left|bottom" + height="22" + label="Upload (L$[AMOUNT])" + layout="topleft" + left="45" + name="ok_btn" + top_pad="60" + width="150" /> + <button + follows="right|bottom" + height="22" + label="Cancel" + label_selected="Cancel" + layout="topleft" + name="cancel_btn" + left_pad="5" + width="90" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_animation_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml index cb6b2f6ebc..cb6b2f6ebc 100644 --- a/indra/newview/skins/default/xui/en/floater_animation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml diff --git a/indra/newview/skins/default/xui/en/floater_avatar.xml b/indra/newview/skins/default/xui/en/floater_avatar.xml index 82c3403008..cd5cca02bd 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar.xml @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" ignore_ui_scale="false" legacy_header_height="225" can_minimize="true" can_close="true" can_resize="true" min_height="230" - min_width="450" + min_width="515" height="230" layout="topleft" name="Avatar" diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml index cbbbeb6094..1a55dc2e2c 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" legacy_header_height="18" can_resize="true" height="350" diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml index 35918e9705..38428b36fc 100644 --- a/indra/newview/skins/default/xui/en/floater_build_options.xml +++ b/indra/newview/skins/default/xui/en/floater_build_options.xml @@ -1,70 +1,13 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - height="198" + height="170" layout="topleft" name="build options floater" help_topic="build_options_floater" save_rect="true" title="GRID OPTIONS" width="264"> - <floater.string - name="grid_screen_text"> - Screen - </floater.string> - <floater.string - name="grid_local_text"> - Local - </floater.string> - <floater.string - name="grid_world_text"> - World - </floater.string> - <floater.string - name="grid_reference_text"> - Reference - </floater.string> - <floater.string - name="grid_attachment_text"> - Attachment - </floater.string> - <text - type="string" - length="1" - follows="left|top" - height="16" - layout="topleft" - left="10" - tool_tip="Grid opacity" - name="grid_mode_label" - top_pad="30" - width="123"> - Mode - </text> - <combo_box - height="23" - layout="topleft" - left_pad="9" - follows="left|top" - name="combobox grid mode" - tool_tip="Choose the type of grid ruler for positioning the object" - top_delta="-3" - width="108"> - <combo_box.item - label="World grid" - name="World" - value="World" /> - <combo_box.item - label="Local grid" - name="Local" - value="Local" /> - <combo_box.item - label="Reference grid" - name="Reference" - value="Reference" /> - <combo_box.commit_callback - function="GridOptions.gridMode"/> - </combo_box> <spinner control_name="GridResolution" follows="left|top" @@ -77,7 +20,7 @@ max_val="5" min_val="0.01" name="GridResolution" - top_pad="4" + top_pad="30" width="200" /> <spinner control_name="GridDrawSize" diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml index 92001534e7..ac96a70805 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml @@ -62,7 +62,7 @@ layout="topleft" left="10" name="buy_text" - text_color="white" + text_color="White" top="220" use_ellipses="true" width="260"> diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml index 6afa24d04a..553c5d51d0 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml @@ -215,7 +215,7 @@ <text type="string" length="1" - text_color="0.7 0.7 0.7 0.5" + text_color="LtGray_50" follows="top|left" layout="topleft" halign="right" @@ -229,7 +229,7 @@ <text type="string" length="1" - text_color="0.7 0.7 0.7 0.5" + text_color="LtGray_50" follows="top|left" layout="topleft" halign="right" @@ -243,7 +243,7 @@ Re-enter amount to see the latest exchange rate. <text type="string" length="1" - text_color="0.7 0.7 0.7 0.5" + text_color="LtGray_50" follows="top|left" layout="topleft" halign="right" @@ -257,7 +257,7 @@ Re-enter amount to see the latest exchange rate. <text type="string" length="1" - text_color="0.7 0.7 0.7 0.5" + text_color="LtGray_50" follows="top|left" layout="topleft" halign="right" diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml index 8dfb6ba00c..5fdd4aa49d 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml @@ -89,7 +89,7 @@ left_delta="0" line_spacing.pixels="7" name="buy_text" - text_color="white" + text_color="White" top_pad="5" use_ellipses="true" width="260" @@ -106,7 +106,7 @@ Buy for L$[AMOUNT] from: left_delta="0" line_spacing.pixels="7" name="buy_name_text" - text_color="white" + text_color="White" top_pad="5" use_ellipses="true" width="260"> diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 4673c6def5..22bc488a92 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -1,8 +1,9 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="specified" - specified_left="458" - specified_bottom="80" + positioning="specified" + left="458" + bottom="-80" + follows="left|bottom" legacy_header_height="18" can_minimize="true" can_close="true" 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 63992462b3..688a01ce7b 100644 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/floater_chat_bar.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="specified" - specified_left="10" - specified_bottom="10" + positioning="specified" + left="10" + bottom="-10" height="60" layout="topleft" legacy_header_height="25" diff --git a/indra/newview/skins/default/xui/en/floater_choose_group.xml b/indra/newview/skins/default/xui/en/floater_choose_group.xml index dc1ee5f24e..2cf6e682fd 100644 --- a/indra/newview/skins/default/xui/en/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/en/floater_choose_group.xml @@ -20,7 +20,7 @@ Choose a group: </text> <scroll_list - height="160" + height="165" layout="topleft" left_delta="0" name="group list" diff --git a/indra/newview/skins/default/xui/en/floater_critical.xml b/indra/newview/skins/default/xui/en/floater_critical.xml index 13b15bf724..143bcb4430 100644 --- a/indra/newview/skins/default/xui/en/floater_critical.xml +++ b/indra/newview/skins/default/xui/en/floater_critical.xml @@ -6,7 +6,7 @@ height="500" layout="topleft" name="modal container" - open_positioning="centered" + positioning="centered" width="600"> <button height="20" diff --git a/indra/newview/skins/default/xui/en/floater_destinations.xml b/indra/newview/skins/default/xui/en/floater_destinations.xml index 373114a1eb..39aa8e07bb 100644 --- a/indra/newview/skins/default/xui/en/floater_destinations.xml +++ b/indra/newview/skins/default/xui/en/floater_destinations.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" ignore_ui_scale="false" legacy_header_height="225" can_minimize="true" diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml index 49aa8f3840..77adb5524e 100644 --- a/indra/newview/skins/default/xui/en/floater_fast_timers.xml +++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml @@ -22,7 +22,6 @@ top="5" width="180" height="40" - pad_bottom="-5" label="Pause" font="SansSerifHuge"/> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml index b96a94a849..200e9b9537 100644 --- a/indra/newview/skins/default/xui/en/floater_gesture.xml +++ b/indra/newview/skins/default/xui/en/floater_gesture.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" save_rect="true" legacy_header_height="18" can_resize="true" diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index 66bb9d3cea..9deb0d2030 100644 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -132,6 +132,28 @@ name="vbo" tool_tip="Enabling this on modern hardware gives a performance gain. However, older hardware often has poor implementations of VBOs and you may get crashes when this is enabled." width="315" /> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="tc label" + top_pad="10" + width="188"> + Enable S3TC: + </text> + <check_box + control_name="RenderCompressTextures" + height="16" + initial_value="true" + label="Enable Texture Compression (requires restart)" + layout="topleft" + left_pad="10" + name="texture compression" + tool_tip="Compresses textures in video memory, allowing for higher resolution textures to be loaded at the cost of some color quality." + width="315" /> <slider control_name="TextureMemory" decimal_digits="0" diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml index cd075abc41..c06cb63f8a 100644 --- a/indra/newview/skins/default/xui/en/floater_help_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" legacy_header_height="18" can_resize="true" height="600" 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..82014e8836 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,10 +73,11 @@ 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" @@ -84,7 +85,7 @@ layout="bottomleft" name="chat_editor" tab_group="3" - width="249"> + width="236"> </line_editor> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/floater_image_preview.xml b/indra/newview/skins/default/xui/en/floater_image_preview.xml index 86232de1a4..44d2c14cc8 100644 --- a/indra/newview/skins/default/xui/en/floater_image_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_image_preview.xml @@ -2,7 +2,7 @@ <floater legacy_header_height="18" can_minimize="false" - height="440" + height="460" layout="topleft" name="Image Preview" help_topic="image_preview" @@ -108,7 +108,7 @@ <text type="string" length="1" - bottom="225" + bottom="250" height="45" word_wrap="true" follows="top|left" @@ -137,7 +137,7 @@ Try saving image as 24 bit Targa (.tga). layout="topleft" left="165" name="cancel_btn" - top="410" + top="430" width="125" /> <button follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml index 6e1bb8fcd0..59f6a9434c 100644 --- a/indra/newview/skins/default/xui/en/floater_joystick.xml +++ b/indra/newview/skins/default/xui/en/floater_joystick.xml @@ -13,6 +13,7 @@ </floater.string> <check_box bottom="38" + height="10" control_name="JoystickEnabled" halign="left" label="Enable Joystick:" @@ -28,6 +29,7 @@ width="380" /> <spinner bottom="48" + height="10" control_name="JoystickAxis1" decimal_digits="0" increment="1" @@ -41,6 +43,7 @@ width="140" /> <spinner bottom="48" + height="10" control_name="JoystickAxis2" decimal_digits="0" increment="1" @@ -54,6 +57,7 @@ width="140" /> <spinner bottom="48" + height="10" control_name="JoystickAxis0" decimal_digits="0" increment="1" @@ -67,6 +71,7 @@ width="140" /> <spinner bottom="68" + height="10" control_name="JoystickAxis4" decimal_digits="0" increment="1" @@ -80,6 +85,7 @@ width="140" /> <spinner bottom="68" + height="10" control_name="JoystickAxis5" decimal_digits="0" increment="1" @@ -93,6 +99,7 @@ width="140" /> <spinner bottom="68" + height="10" control_name="JoystickAxis3" decimal_digits="0" increment="1" @@ -106,6 +113,7 @@ width="140" /> <spinner bottom="88" + height="10" control_name="JoystickAxis6" decimal_digits="0" increment="1" @@ -119,6 +127,7 @@ width="140" /> <check_box bottom_delta="18" + height="10" control_name="ZoomDirect" label="Direct Zoom" layout="topleft" @@ -127,6 +136,7 @@ width="60" /> <check_box bottom_delta="0" + height="10" control_name="Cursor3D" label="3D Cursor" layout="topleft" @@ -135,6 +145,7 @@ width="60" /> <check_box bottom_delta="0" + height="10" control_name="AutoLeveling" label="Auto Level" layout="topleft" @@ -157,6 +168,7 @@ </text> <check_box bottom="127" + height="10" control_name="JoystickAvatarEnabled" halign="center" label="Avatar" @@ -166,6 +178,7 @@ width="60" /> <check_box bottom="127" + height="10" control_name="JoystickBuildEnabled" halign="center" label="Build" @@ -175,6 +188,7 @@ width="60" /> <check_box bottom="127" + height="10" control_name="JoystickFlycamEnabled" halign="center" label="Flycam" @@ -257,6 +271,7 @@ </text> <spinner bottom="144" + height="10" control_name="AvatarAxisScale1" decimal_digits="2" label_width="0" @@ -268,6 +283,7 @@ width="56" /> <spinner bottom="144" + height="10" control_name="BuildAxisScale1" decimal_digits="2" label_width="0" @@ -279,6 +295,7 @@ width="56" /> <spinner bottom="144" + height="10" control_name="FlycamAxisScale1" decimal_digits="2" label_width="0" @@ -301,6 +318,7 @@ </text> <spinner bottom="164" + height="10" control_name="AvatarAxisScale2" decimal_digits="2" label_width="0" @@ -312,6 +330,7 @@ width="56" /> <spinner bottom="164" + height="10" control_name="BuildAxisScale2" decimal_digits="2" label_width="0" @@ -323,6 +342,7 @@ width="56" /> <spinner bottom="164" + height="10" control_name="FlycamAxisScale2" decimal_digits="2" label_width="0" @@ -345,6 +365,7 @@ </text> <spinner bottom="184" + height="10" control_name="AvatarAxisScale0" decimal_digits="2" label_width="0" @@ -356,6 +377,7 @@ width="56" /> <spinner bottom="184" + height="10" control_name="BuildAxisScale0" decimal_digits="2" label_width="0" @@ -367,6 +389,7 @@ width="56" /> <spinner bottom="184" + height="10" control_name="FlycamAxisScale0" decimal_digits="2" label_width="0" @@ -389,6 +412,7 @@ </text> <spinner bottom="204" + height="10" control_name="AvatarAxisScale4" decimal_digits="2" label_width="0" @@ -400,6 +424,7 @@ width="56" /> <spinner bottom="204" + height="10" control_name="BuildAxisScale4" decimal_digits="2" label_width="0" @@ -411,6 +436,7 @@ width="56" /> <spinner bottom="204" + height="10" control_name="FlycamAxisScale4" decimal_digits="2" label_width="0" @@ -433,6 +459,7 @@ </text> <spinner bottom="224" + height="10" control_name="AvatarAxisScale5" decimal_digits="2" label_width="0" @@ -444,6 +471,7 @@ width="56" /> <spinner bottom="224" + height="10" control_name="BuildAxisScale5" decimal_digits="2" label_width="0" @@ -455,6 +483,7 @@ width="56" /> <spinner bottom="224" + height="10" control_name="FlycamAxisScale5" decimal_digits="2" label_width="0" @@ -477,6 +506,7 @@ </text> <spinner bottom="244" + height="10" control_name="BuildAxisScale3" decimal_digits="2" label_width="0" @@ -488,6 +518,7 @@ width="56" /> <spinner bottom="244" + height="10" control_name="FlycamAxisScale3" decimal_digits="2" label_width="0" @@ -510,6 +541,7 @@ </text> <spinner bottom="274" + height="10" control_name="AvatarAxisDeadZone1" decimal_digits="2" increment="0.01" @@ -520,6 +552,7 @@ width="56" /> <spinner bottom="274" + height="10" control_name="BuildAxisDeadZone1" decimal_digits="2" increment="0.01" @@ -530,6 +563,7 @@ width="56" /> <spinner bottom="274" + height="10" control_name="FlycamAxisDeadZone1" decimal_digits="2" increment="0.01" @@ -551,6 +585,7 @@ </text> <spinner bottom="294" + height="10" control_name="AvatarAxisDeadZone2" decimal_digits="2" increment="0.01" @@ -561,6 +596,7 @@ width="56" /> <spinner bottom="294" + height="10" control_name="BuildAxisDeadZone2" decimal_digits="2" increment="0.01" @@ -571,6 +607,7 @@ width="56" /> <spinner bottom="294" + height="10" control_name="FlycamAxisDeadZone2" decimal_digits="2" increment="0.01" @@ -592,6 +629,7 @@ </text> <spinner bottom="314" + height="10" control_name="AvatarAxisDeadZone0" decimal_digits="2" increment="0.01" @@ -602,6 +640,7 @@ width="56" /> <spinner bottom="314" + height="10" control_name="BuildAxisDeadZone0" decimal_digits="2" increment="0.01" @@ -612,6 +651,7 @@ width="56" /> <spinner bottom="314" + height="10" control_name="FlycamAxisDeadZone0" decimal_digits="2" increment="0.01" @@ -633,6 +673,7 @@ </text> <spinner bottom="334" + height="10" control_name="AvatarAxisDeadZone4" decimal_digits="2" increment="0.01" @@ -643,6 +684,7 @@ width="56" /> <spinner bottom="334" + height="10" control_name="BuildAxisDeadZone4" decimal_digits="2" increment="0.01" @@ -653,6 +695,7 @@ width="56" /> <spinner bottom="334" + height="10" control_name="FlycamAxisDeadZone4" decimal_digits="2" increment="0.01" @@ -674,6 +717,7 @@ </text> <spinner bottom="354" + height="10" control_name="AvatarAxisDeadZone5" decimal_digits="2" increment="0.01" @@ -684,6 +728,7 @@ width="56" /> <spinner bottom="354" + height="10" control_name="BuildAxisDeadZone5" decimal_digits="2" increment="0.01" @@ -694,6 +739,7 @@ width="56" /> <spinner bottom="354" + height="10" control_name="FlycamAxisDeadZone5" decimal_digits="2" increment="0.01" @@ -715,6 +761,7 @@ </text> <spinner bottom="374" + height="10" control_name="BuildAxisDeadZone3" decimal_digits="2" increment="0.01" @@ -725,6 +772,7 @@ width="56" /> <spinner bottom="374" + height="10" control_name="FlycamAxisDeadZone3" decimal_digits="2" increment="0.01" @@ -802,6 +850,7 @@ </text> <spinner bottom="430" + height="10" control_name="FlycamAxisScale6" decimal_digits="2" label_width="0" @@ -824,6 +873,7 @@ </text> <spinner bottom="450" + height="10" control_name="FlycamAxisDeadZone6" decimal_digits="2" increment="0.01" diff --git a/indra/newview/skins/default/xui/en/floater_land_holdings.xml b/indra/newview/skins/default/xui/en/floater_land_holdings.xml index 3737294ebe..390ec9ab7d 100644 --- a/indra/newview/skins/default/xui/en/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/en/floater_land_holdings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="centered" + positioning="centered" legacy_header_height="18" height="430" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml index 3eeebcf120..b8893e11d9 100644 --- a/indra/newview/skins/default/xui/en/floater_map.xml +++ b/indra/newview/skins/default/xui/en/floater_map.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" can_minimize="true" can_resize="true" chrome="true" diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml index 498a9b6ce0..b98f280b56 100644 --- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml +++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <floater - open_positioning="cascading" + positioning="cascading" can_close="true" can_resize="true" height="440" @@ -99,7 +99,7 @@ halign="center" font="SansSerifMedium" font_shadow="hard" - valign="bottom"> + valign="top"> Drag items here to create folders </text> </panel> @@ -114,8 +114,8 @@ height="20" wrap="true" halign="left" - valign="bottom" - font="SansSerif" /> + valign="center" + font="SansSerif"/> <button label="Send to Marketplace" tool_tip="Push to my Marketplace Storefront" @@ -132,16 +132,16 @@ </panel> <layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false"> <layout_panel /> - <layout_panel height="45" auto_resize="false"> - <layout_stack orientation="horizontal" left="0" height="45" top="0" width="333" follows="all"> + <layout_panel height="24" auto_resize="false"> + <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all"> <layout_panel width="0" /> - <layout_panel width="45" auto_resize="false"> + <layout_panel width="24" auto_resize="false"> <loading_indicator - height="45" + height="24" layout="topleft" left="0" top="0" - width="45" /> + width="24" /> </layout_panel> <layout_panel width="0" /> </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 eebc5ddc72..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,19 +124,19 @@ left="3" name="lod_tab_border" top_pad="0" - width="619" /> - <text - follows="left|top" - height="18" - initial_value="Source" - layout="topleft" - left="75" - name="source" - text_color="ModelUploaderLabels" - top="15" - valign="center" - value="Source" - width="335" /> + width="629" /> + <text + follows="left|top" + height="18" + initial_value="Source" + layout="topleft" + left="85" + name="source" + text_color="ModelUploaderLabels" + top="15" + valign="center" + value="Source" + width="335"/> <text follows="left|top" halign="right" @@ -163,9 +171,9 @@ name="high_label" text_color="ModelUploaderLabels" top_pad="10" - valign="center" + 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 @@ -240,34 +248,34 @@ <text follows="left|top" halign="right" - height="18" + height="15" initial_value="0" layout="topleft" left_pad="0" name="high_triangles" - valign="center" + valign="top" value="0" width="65" /> <text follows="left|top" halign="right" - height="18" + height="15" initial_value="0" layout="topleft" left_pad="0" name="high_vertices" - valign="center" + valign="top" value="0" width="65" /> <text follows="left|top" halign="center" - height="18" + height="15" initial_value="" layout="topleft" left_pad="0" name="high_status" - valign="center" + valign="top" value="" width="65" /> <icon @@ -277,7 +285,7 @@ left_delta="20" mouse_opaque="true" name="status_icon_high" - top_delta="0" + top_delta="-2" width="16" /> <text follows="left|top" @@ -288,9 +296,9 @@ name="medium_label" text_color="ModelUploaderLabels" top_pad="15" - valign="center" + 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 @@ -368,34 +376,34 @@ <text follows="left|top" halign="right" - height="18" + height="15" initial_value="0" layout="topleft" left_pad="0" name="medium_triangles" - valign="center" + valign="top" value="0" width="65" /> <text follows="left|top" halign="right" - height="18" + height="15" initial_value="0" layout="topleft" left_pad="0" name="medium_vertices" - valign="center" + valign="top" value="0" width="65" /> <text follows="left|top" halign="center" - height="18" + height="15" initial_value="" layout="topleft" left_pad="0" name="medium_status" - valign="center" + valign="top" value="" width="65" /> <icon @@ -405,7 +413,7 @@ left_delta="20" mouse_opaque="true" name="status_icon_medium" - top_delta="0" + top_delta="-2" width="16" /> <text follows="left|top" @@ -416,9 +424,9 @@ name="low_label" text_color="ModelUploaderLabels" top_pad="15" - valign="center" + 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 @@ -496,34 +504,34 @@ <text follows="left|top" halign="right" - height="18" + height="15" initial_value="0" layout="topleft" left_pad="0" name="low_triangles" - valign="center" + valign="top" value="0" width="65" /> <text follows="left|top" halign="right" - height="18" + height="15" initial_value="0" layout="topleft" left_pad="0" name="low_vertices" - valign="center" + valign="top" value="0" width="65" /> <text follows="left|top" halign="center" - height="18" + height="15" initial_value="" layout="topleft" left_pad="0" name="low_status" - valign="center" + valign="top" value="" width="65" /> <icon @@ -533,7 +541,7 @@ left_delta="20" mouse_opaque="true" name="status_icon_low" - top_delta="0" + top_delta="-2" width="16" /> <text follows="left|top" @@ -544,9 +552,9 @@ name="lowest_label" text_color="ModelUploaderLabels" top_pad="15" - valign="center" + 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 @@ -624,34 +632,34 @@ <text follows="left|top" halign="right" - height="18" + height="15" initial_value="0" layout="topleft" left_pad="0" name="lowest_triangles" - valign="center" + valign="top" value="0" width="65" /> <text follows="left|top" halign="right" - height="18" + height="15" initial_value="0" layout="topleft" left_pad="0" name="lowest_vertices" - valign="center" + valign="top" value="0" width="65" /> <text follows="left|top" halign="center" - height="18" + height="15" initial_value="" layout="topleft" left_pad="0" name="lowest_status" - valign="center" + valign="top" value="" width="65" /> <icon @@ -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_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml index 065dab0413..4e7ee7913f 100644 --- a/indra/newview/skins/default/xui/en/floater_moveview.xml +++ b/indra/newview/skins/default/xui/en/floater_moveview.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="specified" - specified_left="320" - specified_bottom="80" + positioning="specified" + left="320" + bottom="-80" legacy_header_height="18" can_dock="false" can_minimize="true" diff --git a/indra/newview/skins/default/xui/en/floater_my_appearance.xml b/indra/newview/skins/default/xui/en/floater_my_appearance.xml index 1c4b25a7b0..fdea7a821a 100644 --- a/indra/newview/skins/default/xui/en/floater_my_appearance.xml +++ b/indra/newview/skins/default/xui/en/floater_my_appearance.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <floater - open_positioning="cascading" + positioning="cascading" legacy_header_height="18" can_resize="true" height="588" 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 cd0b59dc51..184f296255 100644 --- a/indra/newview/skins/default/xui/en/floater_my_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_my_inventory.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <floater - open_positioning="cascading" + positioning="cascading" can_close="true" can_resize="true" height="570" diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index d6d8431150..08d0b00a83 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" can_close="true" can_resize="true" height="570" diff --git a/indra/newview/skins/default/xui/en/floater_picks.xml b/indra/newview/skins/default/xui/en/floater_picks.xml index 7882116662..984894b016 100644 --- a/indra/newview/skins/default/xui/en/floater_picks.xml +++ b/indra/newview/skins/default/xui/en/floater_picks.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <floater - open_positioning="cascading" + positioning="cascading" can_close="true" can_resize="true" height="572" diff --git a/indra/newview/skins/default/xui/en/floater_places.xml b/indra/newview/skins/default/xui/en/floater_places.xml index ccceac0a7b..b241e265a9 100644 --- a/indra/newview/skins/default/xui/en/floater_places.xml +++ b/indra/newview/skins/default/xui/en/floater_places.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <floater - open_positioning="cascading" + positioning="cascading" legacy_header_height="18" can_resize="true" height="588" diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index 402868bb97..bd6faf4ed8 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - open_positioning="centered" + positioning="centered" default_tab_group="1" height="460" layout="topleft" @@ -100,7 +100,7 @@ help_topic="preferences_colors_tab" name="colors" /> <panel - class="panel_preference" + class="panel_preference_privacy" filename="panel_preferences_privacy.xml" label="Privacy" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_preview_animation.xml b/indra/newview/skins/default/xui/en/floater_preview_animation.xml index 8427c7b06f..3ea5f54f2c 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_animation.xml @@ -41,18 +41,26 @@ label_selected="Stop" layout="topleft" left="10" - name="Anim play btn" + name="Inworld" tool_tip="Play this animation so that others can see it" top="47" - width="125" /> + width="125"> + <button.commit_callback + function="PreviewAnim.Play" + parameter="Inworld" /> + </button> <button height="20" label="Play Locally" label_selected="Stop" layout="topleft" left_pad="5" - name="Anim audition btn" + name="Locally" tool_tip="Play this animation so that only you can see it" top_delta="0" - width="125" /> + width="125"> + <button.commit_callback + function="PreviewAnim.Play" + parameter="Locally" /> + </button> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index e6d749a3f0..9561f67941 100644 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -155,6 +155,7 @@ name="object_name" top_delta="0" translate="false" + parse_urls="false" use_ellipses="true" width="185"> Consetetur Sadipscing diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index dd818e2e06..c3e7028dc5 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" legacy_header_height="18" can_resize="true" height="775" diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 0c38283d59..49d64767cc 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" legacy_header_height="18" can_minimize="true" can_close="true" diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index 2fd932786b..9400f7b94f 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -149,13 +149,52 @@ show_per_sec="true" show_bar="false"> </stat_bar> + <stat_bar + name="object_cache_hits" + label="Object Cache Hit Rate" + stat="object_cache_hits" + bar_min="0" + bar_max="100" + unit_label="%" + tick_spacing="20" + label_spacing="20" + show_history="true" + show_per_sec="false" + show_bar="false"> + </stat_bar> </stat_view> <!--Texture Stats--> <stat_view name="texture" label="Texture" show_label="true"> - <stat_bar + <stat_bar + name="texture_cache_hits" + label="Cache Hit Rate" + stat="texture_cache_hits" + bar_min="0.f" + bar_max="100.f" + unit_label="%" + tick_spacing="20" + label_spacing="20" + show_history="true" + show_per_sec="false" + show_bar="false"> + </stat_bar> + <stat_bar + name="texture_cache_read_latency" + label="Cache Read Latency" + unit_label="msec" + stat="texture_cache_read_latency" + bar_min="0.f" + bar_max="1000.f" + tick_spacing="100" + label_spacing="200" + show_history="true" + show_per_sec="false" + show_bar="false"> + </stat_bar> + <stat_bar name="numimagesstat" label="Count" stat="numimagesstat" diff --git a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml index f95f21e63a..a04050e7eb 100644 --- a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml +++ b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml @@ -32,6 +32,26 @@ bg_alpha_color="blue" height="11" min_height="0" + visible="false" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="11" + min_height="0" + visible="true" + background_visible="true"> + <text follows="top|left|right" halign="center" text_color="white">flex</text> + </layout_panel> + <layout_panel name="flex" + auto_resize="true" + user_resize="true" + bg_alpha_color="blue" + height="11" + min_height="0" background_visible="true"> <text follows="top|left|right" halign="center" text_color="white">flex</text> </layout_panel> diff --git a/indra/newview/skins/default/xui/en/floater_test_text_editor.xml b/indra/newview/skins/default/xui/en/floater_test_text_editor.xml index 548e24efba..e1fefc3631 100644 --- a/indra/newview/skins/default/xui/en/floater_test_text_editor.xml +++ b/indra/newview/skins/default/xui/en/floater_test_text_editor.xml @@ -3,6 +3,7 @@ legacy_header_height="18" can_resize="true" height="600" + single_instance="false" layout="topleft" name="floater_test_text_editor" translate="false" diff --git a/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..d11373ce1d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_minimize="false" + can_tear_off="false" + can_resize="true" + can_drag_on_left="false" + can_close="true" + can_dock="true" + bevel_style="in" + height="300" + layout="topleft" + name="Test Floater" + save_rect="true" + title="TEST FLOATER" + save_dock_state="true" + save_visibility="true" + single_instance="true" + width="650"> + <text left="0" + follows="left|top|bottom" + top="5" + clip_partial="true" + bottom="-5" + width="100" + valign="top"> +this +is +some +text +that +is +top +aligned</text> + <text left_pad="5" + follows="left|top|bottom" + top="5" + bottom="-5" + clip_partial="true" + width="100" + valign="center"> +this +is +some +text +that +is +center +aligned</text> + <text left_pad="5" + follows="left|top|bottom" + top="5" + clip_partial="true" + bottom="-5" + width="100" + valign="bottom"> +this +is +some +text +that +is +bottom +aligned</text> + <text_editor left_pad="5" + follows="left|top|bottom" + top="5" + clip_partial="true" + bottom="-5" + width="100" + valign="top"> +this +is +some +text +that +is +top +aligned + </text_editor> + <text_editor left_pad="5" + follows="left|top|bottom" + top="5" + bottom="-5" + clip_partial="true" + width="100" + valign="center"> +this +is +some +text +that +is +center +aligned + </text_editor> + <text_editor left_pad="5" + follows="left|top|bottom" + top="5" + clip_partial="true" + bottom="-5" + width="100" + valign="bottom"> +this +is +some +text +that +is +bottom +aligned + </text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml index 2df9bb35fe..1d31fbd6dc 100644 --- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml @@ -8,21 +8,7 @@ help_topic="floater_test_textbox" translate="false" width="800"> - <text - type="string" - length="1" - height="90" - layout="topleft" - left="10" - top_pad="30" - width="300"> - First line of multiple lines -Second line of multiple lines -Third line of multiple lines -Fourth line of multiple lines -Fifth line of multiple lines - </text> - <text + <text clip_partial="true" top_pad="10" left="10" diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml index 13c850c86c..10854f5a49 100644 --- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml +++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml @@ -115,6 +115,7 @@ </flyout_button> <check_box bottom_delta="35" + height="10" label="Checkbox" layout="topleft" tool_tip="checkbox" @@ -275,6 +276,7 @@ <!-- "spinner" is a numerical input widget with an up and down arrow to change the value. --> <spinner + height="10" bottom_delta="35" follows="top|left" label="Spinner" 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 cad7d72ed7..ffb8b842f0 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -3,15 +3,17 @@ legacy_header_height="18" can_minimize="false" can_resize="true" - height="290" + height="330" layout="topleft" - min_height="290" + min_height="330" min_width="410" name="texture picker" help_topic="texture_picker" title="PICK: TEXTURE" width="410"> - <floater.string + +<!-- top static --> + <floater.string name="choose_picture"> Click to choose a picture </floater.string> @@ -19,6 +21,16 @@ name="pick title"> Pick: </floater.string> + + <view + left="4" + top="20" + name="preview_widget" + height="165" + width="165" + follows="left|top" + /> + <text type="string" length="1" @@ -34,70 +46,94 @@ width="163"> Multiple textures </text> + + <!-- mode selector --> + <radio_group + control_name="mode_selection" + height="20" + layout="topleft" + left="18" + top_pad="80" + name="mode_selection" + follows="left|top"> + <radio_item + label="Inventory" + name="inventory" + top_delta="20" + layout="topleft" + height="16" + left="0" + value="0" + width="80" /> + <radio_item + label="Local" + left_pad="0" + layout="topleft" + top_delta="0" + height="16" + name="local" + value="1" + width="75" /> + </radio_group> + <!-- --> + <text type="string" length="1" follows="left|top" height="14" layout="topleft" - left_delta="0" + left_delta="-12" name="unknown" - top_pad="80" - width="163"> + top_pad="4" + width=""> Size: [DIMENSIONS] </text> + +<!-- middle: inventory mode --> + <button enabled="false" - follows="left|bottom" - height="20" + follows="left|top" + height="18" label="Default" label_selected="Default" layout="topleft" - left_delta="0" name="Default" - top_pad="4" - width="80" /> + width="73" + left="94" + top="215"/> <button + follows="left|top" + height="20" + label="Blank" + label_selected="Blank" + layout="topleft" + left_delta="0" + name="Blank" + top_pad="5" + width="73" /> + <button enabled="false" - follows="left|bottom" + follows="left|top" height="20" label="None" label_selected="None" layout="topleft" - left_pad="4" + left_delta="0" name="None" - top_delta="0" - width="80" /> - <button - follows="left|bottom" - height="20" - label="Blank" - label_selected="Blank" - layout="topleft" - left="4" - name="Blank" top_pad="5" - width="80" /> - <button - follows="left|bottom" + width="73" /> + <button + follows="left|top" height="28" image_selected="eye_button_active.tga" image_unselected="eye_button_inactive.tga" layout="topleft" - left_pad="50" - top_delta="3" + left_delta="-80" + top_delta="-25" name="Pipette" width="28" /> - <check_box - follows="left|bottom" - height="20" - initial_value="true" - label="Apply now" - layout="topleft" - left="4" - name="apply_immediate_check" - top="262" - width="120" /> <filter_editor follows="left|top|right" height="23" @@ -113,7 +149,7 @@ bg_alpha_color="DkGray2" border="false" follows="all" - height="200" + height="233" layout="topleft" left_delta="0" name="inventory panel" @@ -128,23 +164,89 @@ top_pad="0" left_delta="-3" width="200" /> - <button - follows="right|bottom" + +<!-- middle: local mode --> + <button + follows="left|top" + height="18" + label="Add" + label_selected="Add" + layout="topleft" + left="94" + top="215" + name="l_add_btn" + width="73" + visible="false"/> + <button + enabled="false" + follows="left|top" + height="20" + label="Remove" + label_selected="Remove" + layout="topleft" + left_delta="0" + name="l_rem_btn" + top_pad="5" + width="73" + visible="false"/> + <button + enabled="false" + follows="left|top" + height="20" + label="Upload" + label_selected="Upload" + layout="topleft" + left_delta="0" + name="l_upl_btn" + top_pad="5" + width="73" + visible="false"/> + <scroll_list + name="l_name_list" + left="170" + top="22" + width="235" + height="260" + follows="left|top|right|bottom" + column_padding="0" + can_resize="false" + draw_heading="true" + multi_select="true" + search_column="1" + visible="false"> + <column name="unit_name" label="Name" dynamicwidth="true" /> + <column name="unit_id_HIDDEN" label="ID" width="0" /> + </scroll_list> + +<!-- bottom static --> + <button + follows="bottom" height="20" label="OK" label_selected="OK" layout="topleft" - right="-120" + left="95" + top="-30" name="Select" width="100" /> <button - follows="right|bottom" + follows="bottom" height="20" label="Cancel" label_selected="Cancel" layout="topleft" - right="-10" - left_pad="5" + left_delta="120" + top_delta="0" name="Cancel" width="100" /> + <check_box + follows="left|bottom" + height="20" + initial_value="true" + label="Apply now" + layout="topleft" + left="6" + name="apply_immediate_check" + top_delta="0" + width="120" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml new file mode 100644 index 0000000000..44b6a63bca --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml @@ -0,0 +1,341 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="550"
+ layout="topleft"
+ name="TexFetchDebugger"
+ help_topic="texfetchdebugger"
+ title="Texture Fetching Debugger"
+ width="540">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left="10"
+ name="total_num_fetched_label"
+ top="30"
+ width="400">
+ 1, Total number of fetched textures: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_num_fetching_requests_label"
+ top_delta="25"
+ width="400">
+ 2, Total number of fetching requests: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_num_cache_hits_label"
+ top_delta="25"
+ width="400">
+ 3, Total number of cache hits: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_num_visible_tex_label"
+ top_delta="25"
+ width="400">
+ 4, Total number of visible textures: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_num_visible_tex_fetch_req_label"
+ top_delta="25"
+ width="450">
+ 5, Total number of visible texture fetching requests: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_fetched_data_label"
+ top_delta="25"
+ width="530">
+ 6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_fetched_vis_data_label"
+ top_delta="25"
+ width="480">
+ 7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_fetched_rendered_data_label"
+ top_delta="25"
+ width="530">
+ 8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_cache_read_label"
+ top_delta="25"
+ width="400">
+ 9, Total time on cache readings: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_cache_write_label"
+ top_delta="25"
+ width="400">
+ 10, Total time on cache writings: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_decode_label"
+ top_delta="25"
+ width="400">
+ 11, Total time on decodings: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_gl_label"
+ top_delta="25"
+ width="400">
+ 12, Total time on gl texture creation: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_http_label"
+ top_delta="25"
+ width="400">
+ 13, Total time on HTTP fetching: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_fetch_label"
+ top_delta="25"
+ width="400">
+ 14, Total time on entire fetching: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_refetch_vis_cache_label"
+ top_delta="25"
+ width="540">
+ 15, Refetching visibles from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_refetch_vis_http_label"
+ top_delta="25"
+ width="540">
+ 16, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="20"
+ increment="0.01"
+ initial_value="1.0"
+ label="17, Ratio of Texel/Pixel:"
+ label_width="130"
+ layout="topleft"
+ left_delta="0"
+ max_val="10.0"
+ min_val="0.01"
+ name="texel_pixel_ratio"
+ top_delta="30"
+ width="200">
+ <spinner.commit_callback
+ function="TexFetchDebugger.ChangeTexelPixelRatio" />
+ </spinner>
+ <button
+ follows="left|top"
+ height="20"
+ label="Start"
+ layout="topleft"
+ left_delta="0"
+ name="start_btn"
+ top_delta="30"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.Start" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Reset"
+ layout="topleft"
+ left_pad="7"
+ name="clear_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.Clear" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Close"
+ layout="topleft"
+ left_pad="7"
+ name="close_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.Close" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Cache Read"
+ layout="topleft"
+ left="10"
+ name="cacheread_btn"
+ top_delta="30"
+ width="80">
+ <button.commit_callback
+ function="TexFetchDebugger.CacheRead" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Cache Write"
+ layout="topleft"
+ left_pad="7"
+ name="cachewrite_btn"
+ top_delta="0"
+ width="80">
+ <button.commit_callback
+ function="TexFetchDebugger.CacheWrite" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="HTTP"
+ layout="topleft"
+ left_pad="7"
+ name="http_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.HTTPLoad" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Decode"
+ layout="topleft"
+ left_pad="7"
+ name="decode_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.Decode" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="GL Texture"
+ layout="topleft"
+ left_pad="7"
+ name="gl_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.GLTexture" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Refetch Vis Cache"
+ layout="topleft"
+ left="10"
+ name="refetchviscache_btn"
+ top_delta="30"
+ width="120">
+ <button.commit_callback
+ function="TexFetchDebugger.RefetchVisCache" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Refetch Vis HTTP"
+ layout="topleft"
+ left_pad="7"
+ name="refetchvishttp_btn"
+ top_delta="0"
+ width="120">
+ <button.commit_callback
+ function="TexFetchDebugger.RefetchVisHTTP" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index f9147ea650..e37740d20c 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" legacy_header_height="18" height="580" layout="topleft" @@ -14,7 +14,27 @@ save_visibility="true" sound_flags="0" width="295"> - <floater.string + <floater.string + name="grid_screen_text"> + Screen + </floater.string> + <floater.string + name="grid_local_text"> + Local + </floater.string> + <floater.string + name="grid_world_text"> + World + </floater.string> + <floater.string + name="grid_reference_text"> + Reference + </floater.string> + <floater.string + name="grid_attachment_text"> + Attachment + </floater.string> + <floater.string name="status_rotate"> Drag colored bands to rotate object </floater.string> @@ -312,20 +332,48 @@ top_pad="0" name="checkbox snap to grid" width="134" /> - <button - left_pad="0" - label="Options..." + <combo_box + height="20" + layout="topleft" + follows="left|top" + name="combobox grid mode" + tool_tip="Choose the type of grid ruler for positioning the object" + top="83" + left="195" + top_pad="0" + width="60"> + <combo_box.item + label="World" + name="World" + value="World" /> + <combo_box.item + label="Local" + name="Local" + value="Local" /> + <combo_box.item + label="Reference" + name="Reference" + value="Reference" /> + <combo_box.commit_callback + function="BuildTool.gridMode"/> + </combo_box> + + <button + left="259" + label="" + image_selected="ForwardArrow_Press" + image_unselected="ForwardArrow_Off" layout="topleft" follows="top|left" name="Options..." tool_tip="See more grid options" top="83" - right="-35" - width="65" - height="21" > + width="25" + height="20" > <button.commit_callback function="BuildTool.gridOptions"/> </button> + <button follows="left|top" height="20" @@ -1158,6 +1206,7 @@ even though the user gets a free copy. label="Modify" layout="topleft" left="10" + height="10" name="checkbox next owner can modify" width="85" /> <check_box diff --git a/indra/newview/skins/default/xui/en/floater_toybox.xml b/indra/newview/skins/default/xui/en/floater_toybox.xml index 72e6187a14..d8211c24a7 100644 --- a/indra/newview/skins/default/xui/en/floater_toybox.xml +++ b/indra/newview/skins/default/xui/en/floater_toybox.xml @@ -10,7 +10,7 @@ layout="topleft" legacy_header_height="18" name="Toybox" - open_positioning="centered" + positioning="centered" save_rect="true" single_instance="true" title="TOOLBAR BUTTONS" @@ -18,7 +18,7 @@ <text follows="left|top" font="SansSerifMedium" - valign="bottom" + valign="top" halign="left" height="20" layout="topleft" @@ -33,7 +33,7 @@ <text follows="left|top" font="SansSerifMedium" - valign="bottom" + valign="top" halign="left" height="20" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index cea19ec75c..dce2720cf8 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - open_positioning="cascading" + positioning="cascading" can_resize="true" can_minimize="true" can_close="true" @@ -71,7 +71,7 @@ layout="topleft" left_pad="10" name="user_text" - text_color="white" + text_color="White" top="4" use_ellipses="true" value="My Avatar:" diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 77fb21e27c..35cb2670d0 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -36,15 +36,20 @@ <string name="effect_Cyber">Cyber</string> <string name="effect_DeepBot">DeepBot</string> <string name="effect_Demon">Demon</string> + <string name="effect_Female Elf">Female Elf</string> <string name="effect_Flirty">Flirty</string> <string name="effect_Foxy">Foxy</string> - <string name="effect_Halloween_2010_Bonus">Halloween_2010_Bonus</string> + <string name="effect_Halloween 2010 Bonus">Halloween_2010_Bonus</string> <string name="effect_Helium">Helium</string> <string name="effect_Husky">Husky</string> + <string name="effect_Husky Whisper">Husky Whisper</string> <string name="effect_Intercom">Intercom</string> + <string name="effect_Julia">Julia</string> + <string name="effect_Lo Lilt">Lo Lilt</string> <string name="effect_Macho">Macho</string> <string name="effect_Micro">Micro</string> <string name="effect_Mini">Mini</string> + <string name="effect_Model">Model</string> <string name="effect_Nano">Nano</string> <string name="effect_Nightmare">Nightmare</string> <string name="effect_PopBot">PopBot</string> @@ -52,10 +57,12 @@ <string name="effect_Radio">Radio</string> <string name="effect_Robot">Robot</string> <string name="effect_Roxanne">Roxanne</string> + <string name="effect_Rumble">Rumble</string> <string name="effect_Sabrina">Sabrina</string> <string name="effect_Samantha">Samantha</string> <string name="effect_Sexy">Sexy</string> <string name="effect_Shorty">Shorty</string> + <string name="effect_Smaller">Smaller</string> <string name="effect_Sneaky">Sneaky</string> <string name="effect_Stallion">Stallion</string> <string name="effect_Sultry">Sultry</string> diff --git a/indra/newview/skins/default/xui/en/floater_window_size.xml b/indra/newview/skins/default/xui/en/floater_window_size.xml index 355d257785..115fe413f3 100644 --- a/indra/newview/skins/default/xui/en/floater_window_size.xml +++ b/indra/newview/skins/default/xui/en/floater_window_size.xml @@ -28,22 +28,50 @@ tool_tip="width x height" top_pad="5" width="179"> - <combo_box.item - label="1000 x 700 (default)" - name="item0" - value="1000 x 700" /> - <combo_box.item - label="1024 x 768" - name="item1" - value="1024 x 768" /> - <combo_box.item - label="1280 x 720 (720p)" - name="item2" - value="1280 x 720" /> - <combo_box.item - label="1920 x 1080 (1080p)" - name="item3" - value="1920 x 1080" /> + <combo_box.item + label="1000 x 700 (default)" + name="item1" + value="1000 x 700" /> + <combo_box.item + label="1024 x 768 (4:3 XGA)" + name="item2" + value="1024 x 768" /> + <combo_box.item + label="1280 x 720 (16:9 HDTV)" + name="item3" + value="1280 x 720" /> + <combo_box.item + label="1280 x 800 (5:8 WXGA)" + name="item4" + value="1280 x 800" /> + <combo_box.item + label="1280 x 1024 (5:4 SXGA)" + name="item5" + value="1280 x 1024" /> + <combo_box.item + label="1440 x 900 (8:5 WSXGA)" + name="item7" + value="1440 x 900" /> + <combo_box.item + label="1600 x 900 (16:9 HD+)" + name="item8" + value="1600 x 900" /> + <combo_box.item + label="1600 x 1200 (4:3 UXGA)" + name="item9" + value="1600 x 1200" /> + <combo_box.item + label="1680 x 1050 (8:5 WSXGA+)" + name="item10" + value="1680 x 1050" /> + <combo_box.item + label="1920 x 1080 (16:9 HDTV)" + name="item11" + value="1920 x 1080" /> + <combo_box.item + label="1920 x 1200 (8:5 WUXGA)" + name="item12" + value="1920 x 1200" /> </combo_box> <button follows="right|bottom" diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 56d79f62c7..83407069d2 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -2,7 +2,7 @@ <floater legacy_header_height="18" can_resize="true" - open_positioning="centered" + positioning="centered" height="600" layout="topleft" min_height="520" diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml index 8d14c974b4..bfeb8fc470 100644 --- a/indra/newview/skins/default/xui/en/inspect_object.xml +++ b/indra/newview/skins/default/xui/en/inspect_object.xml @@ -56,7 +56,7 @@ owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about halign="right" right="-5" name="price_text" - text_color="white" + text_color="White" top="60" font_shadow="none" width="60"> @@ -90,6 +90,7 @@ L$30,000 follows="all" font="SansSerifSmall" height="13" + clip="false" name="object_media_url" width="207" left_pad="2" diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index ef4a1bc061..b13bf5b508 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -453,6 +453,14 @@ layout="topleft" name="Copy Separator" /> <menu_item_call + label="Cut" + layout="topleft" + name="Cut"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="cut" /> + </menu_item_call> + <menu_item_call label="Copy" layout="topleft" name="Copy"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index cd8550b00d..4e38f005a7 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -153,6 +153,13 @@ function="BuyCurrency" /> </menu_item_call> <menu_item_call + label="Merchant Outbox..." + name="MerchantOutbox"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="outbox" /> + </menu_item_call> + <menu_item_call label="Account dashboard..." name="Manage My Account"> <menu_item_call.on_click @@ -284,6 +291,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" @@ -1869,7 +1882,7 @@ <menu_item_check.on_click function="Advanced.ToggleConsole" parameter="texture" /> - </menu_item_check> + </menu_item_check> <menu_item_check label="Debug Console" name="Debug Console" @@ -1891,28 +1904,6 @@ parameter="notifications_console" /> </menu_item_call> <menu_item_check - label="Texture Size Console" - name="Texture Size" - shortcut="control|shift|6"> - <menu_item_check.on_check - function="Advanced.CheckConsole" - parameter="texture size" /> - <menu_item_check.on_click - function="Advanced.ToggleConsole" - parameter="texture size" /> - </menu_item_check> - <menu_item_check - label="Texture Category Console" - name="Texture Category" - shortcut="control|shift|7"> - <menu_item_check.on_check - function="Advanced.CheckConsole" - parameter="texture category" /> - <menu_item_check.on_click - function="Advanced.ToggleConsole" - parameter="texture category" /> - </menu_item_check> - <menu_item_check label="Fast Timers" name="Fast Timers" shortcut="control|shift|9" @@ -1946,7 +1937,20 @@ function="Advanced.ToggleConsole" parameter="scene view" /> </menu_item_check> - + <menu_item_call + enabled="false" + visible="false" + label="Texture Fetch Debug Console" + name="Texture Fetch Debug Console"> + <menu_item_call.on_click + function="Floater.Show" + parameter="tex_fetch_debugger" /> + <on_enable + function="Develop.SetTexFetchDebugger" /> + <on_visible + function="Develop.SetTexFetchDebugger" /> + </menu_item_call> + <menu_item_separator/> <menu_item_call @@ -2432,6 +2436,52 @@ function="Advanced.ToggleInfoDisplay" parameter="sculpt" /> </menu_item_check> + <menu + create_jump_keys="true" + label="Texture Density" + name="Texture Density" + tear_off="true"> + <menu_item_check + label="None" + name="None"> + <menu_item_check.on_check + function="Advanced.CheckDisplayTextureDensity" + parameter="none" /> + <menu_item_check.on_click + function="Advanced.SetDisplayTextureDensity" + parameter="none" /> + </menu_item_check> + <menu_item_check + label="Current" + name="Current"> + <menu_item_check.on_check + function="Advanced.CheckDisplayTextureDensity" + parameter="current" /> + <menu_item_check.on_click + function="Advanced.SetDisplayTextureDensity" + parameter="current" /> + </menu_item_check> + <menu_item_check + label="Desired" + name="Desired"> + <menu_item_check.on_check + function="Advanced.CheckDisplayTextureDensity" + parameter="desired" /> + <menu_item_check.on_click + function="Advanced.SetDisplayTextureDensity" + parameter="desired" /> + </menu_item_check> + <menu_item_check + label="Full" + name="Full"> + <menu_item_check.on_check + function="Advanced.CheckDisplayTextureDensity" + parameter="full" /> + <menu_item_check.on_click + function="Advanced.SetDisplayTextureDensity" + parameter="full" /> + </menu_item_check> + </menu> </menu> <menu create_jump_keys="true" @@ -2599,16 +2649,6 @@ parameter="TextureLoadFullRes" /> </menu_item_check> <menu_item_check - label="Audit Textures" - name="Audit Textures"> - <menu_item_check.on_check - function="CheckControl" - parameter="AuditTexture" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="AuditTexture" /> - </menu_item_check> - <menu_item_check label="Texture Atlas (experimental)" name="Texture Atlas"> <menu_item_check.on_check @@ -3261,6 +3301,14 @@ <menu_item_call.on_click function="Advanced.CompressImage" /> </menu_item_call> + + <menu_item_call + label="Enable Visual Leak Detector" + name="Enable Visual Leak Detector"> + <menu_item_call.on_click + function="Advanced.ToggleVisualLeakDetector" /> + </menu_item_call> + <menu_item_check label="Output Debug Minidump" name="Output Debug Minidump"> @@ -3287,6 +3335,7 @@ name="Set Logging Level" tear_off="true"> <menu_item_check + name="Debug" label="Debug"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" @@ -3296,6 +3345,7 @@ parameter="0" /> </menu_item_check> <menu_item_check + name="Info" label="Info"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" @@ -3305,6 +3355,7 @@ parameter="1" /> </menu_item_check> <menu_item_check + name="Warning" label="Warning"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" @@ -3314,6 +3365,7 @@ parameter="2" /> </menu_item_check> <menu_item_check + name="Error" label="Error"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" @@ -3323,6 +3375,7 @@ parameter="3" /> </menu_item_check> <menu_item_check + name="None" label="None"> <menu_item_check.on_check function="Develop.CheckLoggingLevel" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index af75d49353..a26c5bb344 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1245,6 +1245,25 @@ Visit [_URL] for more information? <notification icon="alertmodal.tga" + name="IntelOldDriver" + type="alertmodal"> + There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. + + Visit [_URL] to check for driver updates? + <tag>confirm</tag> + <url option="0" name="url"> + http://www.intel.com/p/en_US/support/detect/graphics + </url> + <usetemplate + ignoretext="My graphics driver is out of date" + name="okcancelignore" + notext="No" + yestext="Yes"/> + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" name="UnknownGPU" type="alertmodal"> Your system contains a graphics card that [APP_NAME] doesn't recognize. @@ -1667,7 +1686,7 @@ Unable to create output file: [FILE] icon="alertmodal.tga" name="DoNotSupportBulkAnimationUpload" type="alertmodal"> -[APP_NAME] does not currently support bulk upload of animation files. +[APP_NAME] does not currently support bulk upload of BVH format animation files. <tag>fail</tag> </notification> @@ -6373,31 +6392,28 @@ Is this OK? <notification icon="notify.tga" name="ScriptQuestionCaution" - priority="high" + priority="critical" persist="true" type="notify"> -An object named '<nolink>[OBJECTNAME]</nolink>', owned by '[NAME]' would like to: - -[QUESTIONS] -If you do not trust this object and its creator, you should deny the request. +Warning: The object '<nolink>[OBJECTNAME]</nolink>' wants total access to your Linden Dollars account. If you allow access, it can remove funds from your account at any time, or empty your account completely, on an ongoing basis with no additional warnings. + +It is rare that such a request is legitimate. Do not allow access if you do not fully understand why it wants access to your account. -Grant this request? <tag>confirm</tag> <form name="form"> <button index="0" name="Grant" - text="Grant"/> + text="Allow total access"/> <button default="true" index="1" name="Deny" text="Deny"/> - <button - index="2" - name="Details" - text="Details..."/> </form> + <footer> +[FOOTERTEXT] + </footer> </notification> <notification @@ -6409,11 +6425,11 @@ Grant this request? <form name="form"> <button index="-2" - name="Mute" + name="Client_Side_Mute" text="Block"/> <button index="-1" - name="Ignore" + name="Client_Side_Ignore" text="Ignore"/> </form> </notification> @@ -6428,11 +6444,11 @@ Grant this request? <form name="form"> <button index="-2" - name="Mute" + name="Client_Side_Mute" text="Block"/> <button index="-1" - name="Ignore" + name="Client_Side_Ignore" text="Ignore"/> </form> </notification> @@ -7696,4 +7712,31 @@ Otherwise, you can look at the Map and find places marked "Infohub". You died and have been teleported to your home location. </global> + <notification + icon="alertmodal.tga" + name="LocalBitmapsUpdateFileNotFound" + persist="true" + type="notify"> +[FNAME] could not be updated because the file could no longer be found. +Disabling future updates for this file. + </notification> + + <notification + icon="alertmodal.tga" + name="LocalBitmapsUpdateFailedFinal" + persist="true" + type="notify"> +[FNAME] could not be opened or decoded for [NRETRIES] attempts, and is now considered broken. +Disabling future updates for this file. + </notification> + + <notification + icon="alertmodal.tga" + name="LocalBitmapsVerifyFail" + persist="true" + type="notify"> +Attempted to add an invalid or unreadable image file [FNAME] which could not be opened or decoded. +Attempt cancelled. + </notification> + </notifications> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 1e6a31d388..7c67fd7f83 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -28,7 +28,7 @@ layout="topleft" left_pad="10" name="title_text" - text_color="white" + text_color="White" top="5" width="250"> Block List diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml index 2645d472f9..5c5c718bdf 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_header.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -23,7 +23,7 @@ <text parse_urls="false" allow_scroll="false" - v_pad = "7" + v_pad = "6" read_only = "true" follows="left|right" font.style="BOLD" @@ -37,7 +37,7 @@ top="0" translate="false" use_ellipses="true" - valign="bottom" + valign="top" value="TestString PleaseIgnore" /> <text allow_scroll="false" @@ -49,7 +49,7 @@ left_pad="5" name="time_box" right="-5" - top="8" + top="7" value="23:30" width="110" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_chat_item.xml b/indra/newview/skins/default/xui/en/panel_chat_item.xml index 6af1105400..1ef99649e6 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_item.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml @@ -16,13 +16,14 @@ top="3" width="18" /> <text_chat - top="5" + top="3" left="30" + right="-10" height="120" text_color="white" word_wrap="true" mouse_opaque="true" - valign="bottom" + valign="top" name="msg_text"> </text_chat> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml index df459b4083..4b05ab27e4 100644 --- a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml @@ -29,7 +29,7 @@ width="380" /> <icon height="16" - color="0.75 0.75 0.75 1" + color="LtGray" follows="top|left" image_name="Inv_Object" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 69a692e2c4..f34b913218 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -164,7 +164,7 @@ layout="topleft" left_pad="8" name="edit_wearable_title" - text_color="white" + text_color="White" top="3" value="Editing Shape" use_ellipses="true" @@ -190,7 +190,7 @@ layout="topleft" left="10" name="description_text" - text_color="white" + text_color="White" top="10" value="Shape:" width="150" /> @@ -254,7 +254,7 @@ name="description" prevalidate_callback="ascii" select_on_focus="true" - text_color="black" + text_color="Black" top_pad="3" width="290" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml index a7178dc288..eea2606125 100644 --- a/indra/newview/skins/default/xui/en/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml @@ -172,7 +172,7 @@ including the Everyone and Owner Roles. draw_heading="true" draw_stripes="false" heading_height="23" - height="130" + height="132" layout="topleft" search_column="1" left="0" diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml index 383e637ace..413e22e444 100644 --- a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <inbox_inventory_panel + accepts_drag_and_drop="false" name="inventory_inbox" start_folder="Received Items" follows="all" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml index 4251128714..2e5d650902 100644 --- a/indra/newview/skins/default/xui/en/panel_instant_message.xml +++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml @@ -15,7 +15,7 @@ <panel background_visible="true" bevel_style="in" - bg_alpha_color="black" + bg_alpha_color="Black" follows="top" height="24" label="im_header" @@ -64,7 +64,7 @@ left_pad="5" name="user_name" parse_urls="false" - text_color="white" + text_color="White" top="8" translate="false" use_ellipses="true" @@ -90,7 +90,7 @@ layout="topleft" left="10" name="message" - text_color="white" + text_color="White" top="33" use_ellipses="true" value="" diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index d2088594dd..fd6e96b9a7 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -271,7 +271,7 @@ <text_editor bg_readonly_color="DkGray2" follows="all" - height="70" + height="75" layout="topleft" left="0" max_length="127" @@ -288,7 +288,7 @@ layout="topleft" left="0" name="folder_label" - top_pad="15" + top_pad="10" value="Landmark location:" width="290" /> <combo_box diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index d6d8b2a83e..1c882bb099 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -80,7 +80,6 @@ top="16" width="288" /> <recent_inventory_panel - accepts_drag_and_drop="false" bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 4bf420b79f..3edeb9aa36 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -70,7 +70,7 @@ layout="topleft" auto_resize="true" user_resize="true" - min_width="480" + min_width="410" name="navigation_layout_panel" width="480"> <panel @@ -148,15 +148,15 @@ layout="topleft" auto_resize="true" user_resize="true" - min_width="315" + min_width="185" name="favorites_layout_panel" - width="315"> + width="320"> <icon follows="top|left" height="25" image_name="ChatBarHandle" layout="topleft" - left="-318" + left="-323" name="resize_handle" top="4" width="5" /> @@ -171,16 +171,17 @@ name="favorite" image_drag_indication="Accordion_ArrowOpened_Off" tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" - width="311"> + width="320"> <label follows="left|top" - height="15" + height="13" layout="topleft" left="10" name="favorites_bar_label" text_color="LtGray" tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" - top="12" + top="13" + valign="bottom" width="102"> Favorites Bar </label> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index d492f9bd68..d683116eb8 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -1,35 +1,63 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - height="300" follows="all" + height="300" + help_topic="nearby_chat" layout="topleft" name="nearby_chat" - help_topic="nearby_chat" width="320"> - <check_box - bottom_delta="36" - control_name="TranslateChat" - enabled="true" - height="16" - label="Translate chat" - layout="topleft" - left="5" - name="translate_chat_checkbox" - width="230" /> - <chat_history - parse_urls="true" - bg_readonly_color="ChatHistoryBgColor" - bg_writeable_color="ChatHistoryBgColor" - follows="all" - left="5" - top_delta="17" - layout="topleft" - height="260" - name="chat_history" - parse_highlights="true" - text_color="ChatHistoryTextColor" - text_readonly_color="ChatHistoryTextColor" - right_widget_pad="5" - left_widget_pad="0" - width="315" /> + <layout_stack + follows="all" + height="295" + layout="topleft" + left="0" + name="stack" + top="5" + orientation="vertical" + width="320"> + <layout_panel + auto_resize="false" + height="26" + layout="topleft" + left_delta="0" + name="translate_chat_checkbox_lp" + top_delta="0" + visible="true" + width="313"> + <check_box + top="10" + control_name="TranslateChat" + enabled="true" + height="16" + label="Translate chat" + layout="topleft" + left="5" + name="translate_chat_checkbox" + width="300" /> + </layout_panel> + <layout_panel + auto_resize="true" + height="277" + left_delta="0" + layout="topleft" + name="chat_history_lp" + width="318"> + <chat_history + bg_readonly_color="ChatHistoryBgColor" + bg_writeable_color="ChatHistoryBgColor" + follows="all" + layout="topleft" + left="5" + left_widget_pad="0" + height="272" + name="chat_history" + parse_highlights="true" + parse_urls="true" + right_widget_pad="5" + text_color="ChatHistoryTextColor" + text_readonly_color="ChatHistoryTextColor" + top="0" + width="313" /> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index f6f62ac54e..94c468e1bb 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -3,8 +3,8 @@ background_opaque="false" border_visible="false" background_visible="true" - bg_alpha_color="1 0.3 0.3 0" - bg_opaque_color="1 0.3 0.3 0" + bg_alpha_color="PanelNotificationBackground" + bg_opaque_color="PanelNotificationBackground" label="notification_panel" layout="topleft" left="0" @@ -20,8 +20,8 @@ border_visible="false" bevel_style="none" background_visible="true" - bg_alpha_color="0.3 0.3 0.3 0" - bg_opaque_color="0.3 0.3 0.3 0" + bg_alpha_color="ToastBackground" + bg_opaque_color="ToastBackground" follows="left|right|top" height="100" label="info_panel" @@ -39,7 +39,7 @@ left="10" name="text_box" read_only="true" - text_color="white" + text_color="White" top="10" visible="false" width="285" @@ -52,7 +52,7 @@ layout="topleft" left="10" name="caution_text_box" - text_color="1 0.82 0.46 1" + text_color="NotifyCautionBoxColor" top="10" visible="false" width="285" @@ -60,7 +60,7 @@ <text_editor h_pad="0" v_pad="0" - bg_readonly_color="0.0 0.0 0.0 0" + bg_readonly_color="Transparent" border_visible="false" embedded_items="false" enabled="false" @@ -73,8 +73,8 @@ name="text_editor_box" read_only="true" tab_stop="false" - text_color="white" - text_readonly_color="white" + text_color="White" + text_readonly_color="White" top="10" visible="false" width="285" diff --git a/indra/newview/skins/default/xui/en/panel_online_status_toast.xml b/indra/newview/skins/default/xui/en/panel_online_status_toast.xml index b1a7697e83..dadbd9c9ab 100644 --- a/indra/newview/skins/default/xui/en/panel_online_status_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_online_status_toast.xml @@ -25,7 +25,7 @@ layout="topleft" left_pad="5" name="message" - text_color="white" + text_color="White" top="15" use_ellipses="true" value="" diff --git a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml index e9427a2388..3f67a48b14 100644 --- a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml +++ b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml @@ -85,6 +85,7 @@ top_delta="0" width="95" /> <check_box + height="10" bottom_delta="20" follows="left|top" label="Constrain proportions" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 9827180aa7..24882988b0 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -331,7 +331,7 @@ </text> <radio_group control_name="LetterKeysFocusChatBar" - height="20" + height="34" layout="topleft" left="35" top_pad="0" @@ -339,7 +339,7 @@ <radio_item label="Starts local chat" name="radio_start_chat" - top_delta="20" + top="0" layout="topleft" height="16" left="0" @@ -364,7 +364,7 @@ layout="topleft" left="30" name="title_afk_text" - top_pad="15" + top_pad="5" width="190"> Away timeout: </text> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index 1f92244eb9..b71586aab1 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -63,7 +63,7 @@ layout="topleft" left_pad="0" name="mute_chb_label" - top_delta="0" + top_delta="-1" width="150" wrap="true"> Mute when minimized diff --git a/indra/newview/skins/default/xui/en/panel_script_question_toast.xml b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml new file mode 100644 index 0000000000..b0436bb6dc --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<panel + background_opaque="false" + border_visible="false" + background_visible="true" + bg_alpha_color="PanelNotificationBackground" + bg_opaque_color="PanelNotificationBackground" + chrome="true" + height="270" + label="script_question_panel" + layout="topleft" + left="0" + name="panel_script_question_toast" + top="0" + width="305"> + <text + follows="left|right|top" + font="SansSerifBold" + height="160" + layout="topleft" + left="10" + mouse_opaque="false" + name="top_info_message" + parse_highlights="true" + parse_urls="true" + text_color="NotifyCautionBoxColor" + top="10" + value="" + width="285" + wrap="true"/> + <panel + background_visible="false" + follows="left|right|top" + height="30" + label="buttons_panel" + layout="topleft" + name="buttons_panel" + top_pad="10" + width="285"> + </panel> + <text + follows="all" + font="SansSerifBold" + height="55" + layout="topleft" + mouse_opaque="false" + name="bottom_info_message" + parse_highlights="true" + parse_urls="true" + text_color="NotifyCautionBoxColor" + top_pad="5" + value="" + width="285" + wrap="true"/> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml index 9057ebb65e..71d808fa4b 100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml @@ -114,6 +114,7 @@ width="95" /> <check_box bottom_delta="20" + height="10" follows="left|top" label="Constrain proportions" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml index b966358f18..781ab17403 100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml @@ -132,6 +132,7 @@ width="95" /> <check_box bottom_delta="20" + height="10" follows="left|top" label="Constrain proportions" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml index 5bd383b81e..0dd357aa1a 100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml @@ -119,6 +119,7 @@ top_delta="0" width="95" /> <check_box + height="10" bottom_delta="20" label="Constrain proportions" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index d453a970e7..3aa34439f1 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -35,8 +35,8 @@ </panel.string> <panel height="18" - left="-370" - width="160" + left="-395" + width="185" top="1" follows="right|top" name="balance_bg"> @@ -67,7 +67,6 @@ label_shadow="true" name="buyL" pad_right="0" - pad_bottom="2" tool_tip="Click to buy more L$" top="0" width="80" /> @@ -87,7 +86,6 @@ left_pad="0" label_shadow="true" name="goShop" - pad_bottom="2" tool_tip="Open Second Life Marketplace" top="0" width="65" /> diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml index 5e74689c5a..007b73a4bc 100644 --- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml +++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml @@ -13,7 +13,7 @@ follows="left|right" background_opaque="false" background_visible="true" - bg_alpha_color="0.0 0.0 0.0 0.0" > + bg_alpha_color="SysWellItemUnselected" > <text clip_partial="true" top="2" @@ -22,7 +22,7 @@ height="28" layout="topleft" follows="right|left" - text_color="white" + text_color="White" use_ellipses="true" word_wrap="true" mouse_opaque="false" diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml index c89e1dc215..c5b0be0616 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml @@ -44,7 +44,7 @@ parse_urls="false" use_ellipses="true" name="region" - text_color="white" + text_color="White" top="4" value="..." width="330" /> diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml index 062c403a26..37a904bca8 100644 --- a/indra/newview/skins/default/xui/en/panel_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_toast.xml @@ -10,7 +10,6 @@ --> <floater - open_positioning="none" legacy_header_height="0" header_height="0" name="toast" @@ -59,7 +58,7 @@ left="20" name="toast_text" word_wrap="true" - text_color="white" + text_color="White" top="5" translate="false" use_ellipses="true" diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index fcba937bdb..6ecb57b41d 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -51,7 +51,7 @@ <layout_panel width="330" layout="topleft" - auto_resize="true" + auto_resize="false" user_resize="true" follows="left|right|top" name="inbox_layout_panel" @@ -73,6 +73,7 @@ <string name="InboxLabelWithArg">Received items ([NUM])</string> <string name="InboxLabelNoArg">Received items</string> <button + control_name="InventoryInboxToggleState" label="Received items" font="SansSerifMedium" name="inbox_btn" @@ -104,6 +105,7 @@ [NUM] new </text> <panel + name="inbox_inventory_placeholder_panel" follows="all" left="10" bottom="235" @@ -112,7 +114,7 @@ bg_opaque_color="InventoryBackgroundColor" background_visible="true" background_opaque="true" - tool_tip="Drag and drop items to your inventory to manage and use them" + tool_tip="Drag and drop items to your inventory to use them" > <text name="inbox_inventory_placeholder" diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 6600339ad7..bf2e6bc2d9 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -267,19 +267,19 @@ <combo_box.item label="Touch (default)" name="Touch/grab(default)" - value="Touch/grab (default)" /> + value="Touch" /> <combo_box.item label="Sit on object" name="Sitonobject" - value="Sit on object" /> + value="Sit" /> <combo_box.item label="Buy object" name="Buyobject" - value="Buy object" /> + value="Buy" /> <combo_box.item label="Pay object" name="Payobject" - value="Pay object" /> + value="Pay" /> <combo_box.item label="Open" name="Open" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 3351ffe00f..866ea296c3 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -369,6 +369,9 @@ Please try logging in again in a minute.</string> <string name="anim_yes_happy">Yes (Happy)</string> <string name="anim_yes_head">Yes</string> + <!-- build floater --> + <string name="multiple_textures">Multiple</string> + <!-- world map --> <string name="texture_loading">Loading...</string> <string name="worldmap_offline">Offline</string> @@ -390,6 +393,7 @@ Please try logging in again in a minute.</string> <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string> <string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string> <string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string> + <string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string> <string name="ScriptTakeMoney">Take Linden dollars (L$) from you</string> <string name="ActOnControlInputs">Act on your control inputs</string> <string name="RemapControlInputs">Remap your control inputs</string> @@ -400,8 +404,9 @@ Please try logging in again in a minute.</string> <string name="AddAndRemoveJoints">Add and remove joints with other objects</string> <string name="ChangePermissions">Change its permissions</string> <string name="TrackYourCamera">Track your camera</string> - <string name="ControlYourCamera">Control your camera</string> - <string name="NotConnected">Not Connected</string> + <string name="ControlYourCamera">Control your camera</string> + <string name="TeleportYourAgent">Teleport you</string> + <string name="NotConnected">Not Connected</string> <!-- Sim Access labels --> <string name="SIM_ACCESS_PG">General</string> @@ -2037,7 +2042,7 @@ Returns a string with the requested data about the region <string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string> <string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string> <string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string> - <string name="InventoryInboxNoItems">Certain items you receive, such as premium gifts, will appear here. You may then drag them into your inventory.</string> + <string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string> <string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string> <string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string> <string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string> @@ -3238,6 +3243,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="IM_to_label">To</string> <string name="IM_moderator_label">(Moderator)</string> <string name="Saved_message">(Saved [LONG_TIMESTAMP])</string> + <string name="IM_unblock_only_groups_friends">To see this message, you must uncheck 'Only friends and groups can call or IM me' in Preferences/Privacy.</string> <!-- voice calls --> <string name="answered_call">Your call has been answered</string> diff --git a/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml b/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml index 1bb3188cc8..8a4ccb19f9 100644 --- a/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml @@ -17,13 +17,13 @@ <voice_call_invited_style font="SansSerifSmall" font.style="NORMAL" - color="0.5 0.5 0.5 0.5"/> + color="AvatarListItemIconVoiceInvitedColor"/> <!-- styles for avatar item JOINED to voice call --> <voice_call_joined_style font="SansSerifSmall" font.style="NORMAL" - color="white"/> + color="White"/> <!-- styles for avatar item which HAS LEFT voice call --> <voice_call_left_style @@ -35,11 +35,11 @@ <online_style font="SansSerifSmall" font.style="NORMAL" - color="white"/> + color="White"/> <!-- styles for OFFLINE avatar item --> <offline_style font="SansSerifSmall" font.style="NORMAL" - color="0.5 0.5 0.5 1.0"/> + color="Gray"/> </avatar_list_item> diff --git a/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml b/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml index 0eec002006..0016a8cf53 100644 --- a/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml @@ -24,7 +24,7 @@ parse_urls="false" use_ellipses="true" name="item_name" - text_color="white" + text_color="White" top="5" value="..." width="359" /> diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml index e2baba92a3..2b2c3faf91 100644 --- a/indra/newview/skins/default/xui/en/widgets/button.xml +++ b/indra/newview/skins/default/xui/en/widgets/button.xml @@ -21,7 +21,7 @@ font="SansSerifSmall" hover_glow_amount="0.15" halign="center" - pad_bottom="3" + pad_bottom="1" height="23" scale_image="true" handle_right_mouse="true" diff --git a/indra/newview/skins/default/xui/en/widgets/check_box.xml b/indra/newview/skins/default/xui/en/widgets/check_box.xml index cca64fad2a..8947024e45 100644 --- a/indra/newview/skins/default/xui/en/widgets/check_box.xml +++ b/indra/newview/skins/default/xui/en/widgets/check_box.xml @@ -10,7 +10,7 @@ text_readonly_color="LabelDisabledColor"/> <check_box.check_button name="CheckboxCtrl Button" left="2" - bottom="2" + bottom="1" width="13" height="13" commit_on_return="false" diff --git a/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml b/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml index 96d72c78a6..d83f44737e 100644 --- a/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml @@ -24,7 +24,7 @@ parse_urls="false" use_ellipses="true" name="item_name" - text_color="white" + text_color="White" top="5" value="..." width="359" /> diff --git a/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml index 6c60624805..8c805da048 100644 --- a/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml @@ -9,7 +9,7 @@ width="380"> <item_icon height="16" - color="0.75 0.75 0.75 1" + color="LtGray" follows="top|left" image_name="Inv_Object" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index adbb183317..97a5ae7d4e 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -2,7 +2,7 @@ <!-- See also settings.xml UIFloater* settings for configuration --> <floater name="floater" - open_positioning="none" + positioning="none" layout="topleft" bg_opaque_color="FloaterFocusBackgroundColor" bg_alpha_color="FloaterDefaultBackgroundColor" diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml index 3e2202b20f..0586119681 100644 --- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -11,7 +11,7 @@ label_pad_left - padding to the left of tab button labels halign="center" font="SansSerifSmall" tab_height="21" - label_pad_bottom="2" + label_pad_bottom="1" label_pad_left="4"> <!-- Possible additional attributes for tabs: diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml index 6b8a1ff906..fd54d74af2 100644 --- a/indra/newview/skins/default/xui/es/floater_about_land.xml +++ b/indra/newview/skins/default/xui/es/floater_about_land.xml @@ -373,7 +373,7 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda. </text> <texture_picker label="" name="snapshot_ctrl" tool_tip="Pulse para elegir una imagen"/> <text name="allow_label5"> - a los avatares de esta parcela y chatear con ellos + Los avatares de otras parcelas pueden ver a los avatares de esta parcela y chatear con ellos </text> <check_box label="Ver los avatares" name="SeeAvatarsCheck" tool_tip="Permite que los avatares de otras parcelas vean a los avatares de ésta y chateen con ellos, y también que tú puedas verles y chatear con ellos."/> <text name="landing_point"> @@ -460,12 +460,12 @@ los media: <text name="Limit access to this parcel to:"> Acceso a esta parcela </text> - <check_box label="Permitir el acceso público [MATURITY]" name="public_access"/> + <check_box label="Permitir el acceso público (si no seleccionas esta opción, se crearán lÃneas de prohibición)" name="public_access"/> <text name="Only Allow"> - Restringir el acceso a residentes verificados con: + Permitir únicamente el acceso a los Residentes que: </text> - <check_box label="Información de pago aportada [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Expulsa a los Residentes no identificados."/> - <check_box label="Verificación de edad [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Expulsa a los Residentes que no hayan verificado su edad. Más información en [SUPPORT_SITE]."/> + <check_box label="Han aportado información de pago [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Para poder acceder a esta parcela los Residentes deben haber aportado información de pago en su cuenta. Para más información, ver [SUPPORT_SITE]."/> + <check_box label="Han verificado su edad [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Para poder acceder a esta parcela los Residentes deben haber verificado su edad. Para más información, ver [SUPPORT_SITE]."/> <check_box label="Acceso permitido al grupo: [GROUP]" name="GroupCheck" tool_tip="Elija el grupo en la pestaña General."/> <check_box label="Vender pases a:" name="PassCheck" tool_tip="Permitir acceso temporal a esta parcela"/> <combo_box name="pass_combo"> diff --git a/indra/newview/skins/default/xui/es/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/es/floater_merchant_outbox.xml new file mode 100644 index 0000000000..a7c17fc136 --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_merchant_outbox.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_merchant_outbox" title="BUZÓN DE SALIDA DE COMERCIANTE"> + <string name="OutboxFolderCount1"> + 1 carpeta + </string> + <string name="OutboxFolderCountN"> + [NUM] carpetas + </string> + <string name="OutboxImporting"> + Enviando carpetas... + </string> + <string name="OutboxInitializing"> + Inicializando... + </string> + <panel label=""> + <panel> + <panel name="outbox_inventory_placeholder_panel"> + <text name="outbox_inventory_placeholder_title"> + Cargando... + </text> + </panel> + </panel> + <panel> + <button label="Enviar al Mercado" name="outbox_import_btn" tool_tip="Poner en el escaparate de Mi Mercado"/> + </panel> + </panel> +</floater> 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 e27db5a1c4..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="header_panel"> - <text name="header_text"> - Elige el archivo de modelo - </text> - </panel> - <panel name="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="Buscar..." label_selected="Buscar..." 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="header_panel"> - <text name="header_text"> - Optimizar el modelo - </text> - </panel> - <text name="description"> - Hemos optimizado el rendimiento del modelo, pero puedes ajustarlo más si lo deseas. - </text> - <panel name="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="header_panel"> - <text name="header_text"> - Ajustar la fÃsica - </text> - </panel> - <text name="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="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="header_panel"> - <text name="header_text"> - Revisar - </text> - </panel> - <panel name="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="header_panel"> - <text name="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_test_layout_stacks.xml b/indra/newview/skins/default/xui/es/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..b479d5f6d6 --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_test_layout_stacks.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="LAYOUTSTACK TESTS"/> diff --git a/indra/newview/skins/default/xui/es/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/es/menu_inspect_object_gear.xml index bcdc25894f..9d0a8c50ef 100644 --- a/indra/newview/skins/default/xui/es/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/es/menu_inspect_object_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<menu name="Gear Menu"> +<toggleable_menu name="Gear Menu"> <menu_item_call label="Tocar" name="touch"/> <menu_item_call label="Sentarse" name="sit"/> <menu_item_call label="Pagar" name="pay"/> @@ -12,7 +12,8 @@ <menu_item_call label="Añadir" name="add"/> <menu_item_call label="Denunciar" name="report"/> <menu_item_call label="Ignorar" name="block"/> + <menu_item_call label="No ignorar" name="unblock"/> <menu_item_call label="Acercar el zoom" name="zoom_in"/> <menu_item_call label="Quitar" name="remove"/> <menu_item_call label="Más información" name="more_info"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/es/menu_inventory.xml b/indra/newview/skins/default/xui/es/menu_inventory.xml index f1f1ef091f..4a8f37dee4 100644 --- a/indra/newview/skins/default/xui/es/menu_inventory.xml +++ b/indra/newview/skins/default/xui/es/menu_inventory.xml @@ -84,6 +84,6 @@ <menu_item_call label="Añadir" name="Wearable Add"/> <menu_item_call label="Quitarse" name="Take Off"/> <menu_item_call label="Copiar al Buzón de salida de comerciante" name="Merchant Copy"/> - <menu_item_call label="Mover al Buzón de salida de comerciante" name="Merchant Move"/> + <menu_item_call label="Enviar al Mercado" name="Marketplace Send"/> <menu_item_call label="--sin opciones--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/es/menu_login.xml b/indra/newview/skins/default/xui/es/menu_login.xml index e3abf7ad62..289ac3f075 100644 --- a/indra/newview/skins/default/xui/es/menu_login.xml +++ b/indra/newview/skins/default/xui/es/menu_login.xml @@ -16,8 +16,8 @@ <menu_item_call label="Definir el tamaño de la ventana..." name="Set Window Size..."/> <menu_item_call label="Mostrar los 'TOS'" name="TOS"/> <menu_item_call label="Mostrar mensaje crÃtico" name="Critical"/> - <menu_item_call label="Prueba de navegadores de medios" name="Web Browser Test"/> <menu_item_call label="Prueba de depuración de ventanas de contenido web" name="Web Content Floater Debug Test"/> + <menu label="Configurar el nivel de registro" name="Set Logging Level"/> <menu_item_check label="Mostrar el selector de Grid" name="Show Grid Picker"/> <menu_item_call label="Mostrar la consola de notificaciones" name="Show Notifications Console"/> </menu> diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml index 4762e3f4a4..9522d4eac6 100644 --- a/indra/newview/skins/default/xui/es/menu_viewer.xml +++ b/indra/newview/skins/default/xui/es/menu_viewer.xml @@ -14,14 +14,13 @@ <menu_item_check label="Volar" name="Fly"/> <menu_item_check label="Correr siempre" name="Always Run"/> <menu_item_call label="Parar mis animaciones" name="Stop Animating My Avatar"/> + <menu_item_call label="Caminar / Correr / Volar..." name="Walk / run / fly"/> </menu> <menu label="Estado" name="Status"> <menu_item_call label="Ausente" name="Set Away"/> <menu_item_call label="Ocupado" name="Set Busy"/> </menu> - <menu_item_call label="Solicitar estatus de Administrador" name="Request Admin Options"/> - <menu_item_call label="Dejar el estatus de Administrador" name="Leave Admin Options"/> - <menu_item_call label="Comprar L$" name="Buy and Sell L$"/> + <menu_item_call label="Comprar L$..." name="Buy and Sell L$"/> <menu_item_call label="Panel de control de la cuenta..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=es"/> </menu_item_call> @@ -63,7 +62,7 @@ <menu_item_check label="Propiedades de la parcela" name="Parcel Properties"/> <menu_item_check label="Menú Avanzado" name="Show Advanced Menu"/> </menu> - <menu label="Sol" name="Environment Settings"> + <menu label="Sol" name="Sun"> <menu_item_call label="Amanecer" name="Sunrise"/> <menu_item_call label="MediodÃa" name="Noon"/> <menu_item_call label="Atardecer" name="Sunset"/> @@ -178,22 +177,22 @@ <menu_item_check label="Mostrar el Punto de Mira en la vista subjetiva" name="ShowCrosshairs"/> </menu> <menu label="Objetos representados" name="Rendering Types"> - <menu_item_check label="Simple" name="Simple"/> - <menu_item_check label="Alfa" name="Alpha"/> - <menu_item_check label="Ãrbol" name="Tree"/> - <menu_item_check label="Avatares" name="Character"/> - <menu_item_check label="Parche de superficie" name="Surface Patch"/> - <menu_item_check label="Cielo" name="Sky"/> - <menu_item_check label="Agua" name="Water"/> - <menu_item_check label="Terreno" name="Ground"/> - <menu_item_check label="volumen" name="Volume"/> - <menu_item_check label="Hierba" name="Grass"/> - <menu_item_check label="Nubes" name="Clouds"/> - <menu_item_check label="PartÃculas" name="Particles"/> - <menu_item_check label="Efectos de relieve" name="Bump"/> + <menu_item_check label="Simple" name="Rendering Type Simple"/> + <menu_item_check label="Alfa" name="Rendering Type Alpha"/> + <menu_item_check label="Ãrbol" name="Rendering Type Tree"/> + <menu_item_check label="Avatares" name="Rendering Type Character"/> + <menu_item_check label="Parcela de superficie" name="Rendering Type Surface Patch"/> + <menu_item_check label="Cielo" name="Rendering Type Sky"/> + <menu_item_check label="Agua" name="Rendering Type Water"/> + <menu_item_check label="Terreno" name="Rendering Type Ground"/> + <menu_item_check label="Volumen" name="Rendering Type Volume"/> + <menu_item_check label="Hierba" name="Rendering Type Grass"/> + <menu_item_check label="Nubes" name="Rendering Type Clouds"/> + <menu_item_check label="PartÃculas" name="Rendering Type Particles"/> + <menu_item_check label="Efectos de relieve" name="Rendering Type Bump"/> </menu> <menu label="Rasgos renderizados" name="Rendering Features"> - <menu_item_check label="UI" name="UI"/> + <menu_item_check label="UI" name="ToggleUI"/> <menu_item_check label="Seleccionado" name="Selected"/> <menu_item_check label="Realzados" name="Highlighted"/> <menu_item_check label="Texturas dinámicas" name="Dynamic Textures"/> @@ -206,8 +205,6 @@ <menu_item_check label="Vista subjetiva suavizada" name="Mouse Smoothing"/> <menu_item_call label="Recuperar las teclas" name="Release Keys"/> <menu label="Atajos de teclado" name="Shortcuts"> - <menu_item_call label="Imagen ([COST] L$)..." name="Upload Image"/> - <menu_item_check label="Buscar" name="Search"/> <menu_item_check label="Mostrar el menú Avanzado - acceso directo antiguo" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Cerrar la ventana" name="Close Window"/> <menu_item_call label="Cerrar todas las ventanas" name="Close All Windows"/> @@ -216,13 +213,6 @@ <menu_item_check label="Flycam del joystick" name="Joystick Flycam"/> <menu_item_call label="Volver a la vista por defecto" name="Reset View"/> <menu_item_call label="Mirar al último que habló" name="Look at Last Chatter"/> - <menu label="Seleccionar la herramienta de construcción" name="Select Tool"> - <menu_item_call label="Herramienta Visión" name="Focus"/> - <menu_item_call label="Herramienta Mover" name="Move"/> - <menu_item_call label="Herramienta Editar" name="Edit"/> - <menu_item_call label="Herramienta Crear" name="Create"/> - <menu_item_call label="Herramienta Terreno" name="Land"/> - </menu> <menu_item_call label="Acercar el zoom" name="Zoom In"/> <menu_item_call label="Zoom por defecto" name="Zoom Default"/> <menu_item_call label="Alejar el zoom" name="Zoom Out"/> @@ -278,6 +268,7 @@ <menu_item_check label="Crear cola" name="Build Queue"/> <menu_item_check label="Vectores de viento" name="Wind Vectors"/> <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> <menu label="Rendering" name="Rendering"> @@ -300,11 +291,10 @@ <menu_item_call label="Drop a Packet" name="Drop a Packet"/> </menu> <menu_item_call label="Bumps, Pushes & Hits" name="Bumps, Pushes &amp; Hits"/> - <menu label="World" name="World"> - <menu_item_check label="Region Sun Override" name="Sim Sun Override"/> - <menu_item_check label="Beacon flashing effect" name="Cheesy Beacon"/> - <menu_item_check label="Fixed Weather" name="Fixed Weather"/> - <menu_item_call label="Dump Region Object Cache" name="Dump Region Object Cache"/> + <menu label="Mundo virtual" name="DevelopWorld"> + <menu_item_check label="Anular el sol del Sim" name="Sim Sun Override"/> + <menu_item_check label="MeteorologÃa fija" name="Fixed Weather"/> + <menu_item_call label="Volcar la caché de objetos de la región" name="Dump Region Object Cache"/> </menu> <menu label="UI" name="UI"> <menu_item_call label="Prueba de navegadores de medios" name="Web Browser Test"/> @@ -324,11 +314,11 @@ </menu> <menu label="Avatar" name="Character"> <menu label="Grab Baked Texture" name="Grab Baked Texture"> - <menu_item_call label="Iris" name="Iris"/> - <menu_item_call label="Head" name="Head"/> - <menu_item_call label="Upper Body" name="Upper Body"/> - <menu_item_call label="Lower Body" name="Lower Body"/> - <menu_item_call label="Skirt" name="Skirt"/> + <menu_item_call label="Iris" name="Grab Iris"/> + <menu_item_call label="Cabeza" name="Grab Head"/> + <menu_item_call label="Parte superior del cuerpo" name="Grab Upper Body"/> + <menu_item_call label="Parte inferior del cuerpo" name="Grab Lower Body"/> + <menu_item_call label="Falda" name="Grab Skirt"/> </menu> <menu label="Character Tests" name="Character Tests"> <menu_item_call label="Toggle Character Geometry" name="Toggle Character Geometry"/> @@ -345,17 +335,19 @@ <menu_item_check label="HTTP Textures" name="HTTP Textures"/> <menu_item_check label="Inventario HTTP" name="HTTP Inventory"/> <menu_item_check label="Console Window on next Run" name="Console Window"/> + <menu label="Configurar el nivel de registro" name="Set Logging Level"/> <menu_item_call label="Request Admin Status" name="Request Admin Options"/> <menu_item_call label="Leave Admin Status" name="Leave Admin Options"/> <menu_item_check label="Show Admin Menu" name="View Admin Options"/> </menu> <menu label="Admin" name="Admin"> - <menu label="Object"> - <menu_item_call label="Coger una copia" name="Take Copy"/> - <menu_item_call label="Force Owner To Me" name="Force Owner To Me"/> - <menu_item_call label="Force Owner Permissive" name="Force Owner Permissive"/> + <menu label="Objeto" name="AdminObject"> + <menu_item_call label="Tomar una copia" name="Admin Take Copy"/> + <menu_item_call label="Forzar que yo sea el propietario" name="Force Owner To Me"/> + <menu_item_call label="Forzar permiso al propietario" name="Force Owner Permissive"/> <menu_item_call label="Eliminar" name="Delete"/> - <menu_item_call label="Lock" name="Lock"/> + <menu_item_call label="Bloquear" name="Lock"/> + <menu_item_call label="Obtener ID de objetos" name="Get Assets IDs"/> </menu> <menu label="Parcel" name="Parcel"> <menu_item_call label="Force Owner To Me" name="Owner To Me"/> @@ -372,5 +364,16 @@ <menu label="Take Off Clothing" name="Take Off Clothing"> <menu_item_call label="FÃsica" name="Physics"/> </menu> + <menu label="Ayuda" name="DeprecatedHelp"> + <menu_item_call label="Blog oficial" name="Official Linden Blog"/> + <menu_item_call label="Portal de programación" name="Scripting Portal"/> + <menu label="Informes de fallos" name="Bug Reporting"> + <menu_item_call label="Public Issue Tracker" name="Public Issue Tracker"/> + <menu_item_call label="Ayuda del Public Issue Tracker" name="Publc Issue Tracker Help"/> + <menu_item_call label="Informes de fallos - instrucciones" name="Bug Reporing 101"/> + <menu_item_call label="Problemas de seguridad" name="Security Issues"/> + <menu_item_call label="Wiki QA" name="QA Wiki"/> + </menu> + </menu> </menu> </menu_bar> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index e0a20683c5..d47c3d7ad8 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -86,17 +86,38 @@ Asegúrate de que tu conexión a Internet está funcionando adecuadamente. <usetemplate canceltext="Cancelar" name="yesnocancelbuttons" notext="No guardarlos" yestext="Guardarlos"/> </notification> <notification name="ConfirmNoCopyToOutbox"> - No tienes permiso para copiar este objeto en el Buzón de salida de comerciante. ¿Estás seguro de que quieres mover el objeto siguiente? - [ITEM_NAME] - <usetemplate name="okcancelbuttons" notext="No" yestext="SÃ"/> + No tienes permiso para copiar uno o varios de estos objetos en el Buzón de salida de comerciante. Puedes moverlos o dejártelos. + <usetemplate name="okcancelbuttons" notext="No mover objeto(s)" yestext="Mover objeto(s)"/> + </notification> + <notification name="OutboxFolderCreated"> + Se ha creado una carpeta nueva para cada objeto que has transferido al nivel superior de tu Buzón de salida de comerciante. + <usetemplate ignoretext="Se ha creado una carpeta nueva en el Buzón de salida de comerciante" name="okignore" yestext="OK"/> </notification> - <notification name="OutboxUploadComplete"> - EnvÃo al mercado finalizado. - <usetemplate name="okbutton" yestext="¡Hurra!"/> + <notification name="OutboxImportComplete"> + Éxito + +Todas las carpetas se han enviado correctamente al Mercado. + <usetemplate ignoretext="Todas las carpetas enviadas al Mercado" name="okignore" yestext="OK"/> + </notification> + <notification name="OutboxImportHadErrors"> + Algunas carpetas no se han transferido + +Han ocurrido errores al enviar algunas carpetas al Mercado. Dichas carpetas todavÃa están en tu Buzón de salida de comerciante. + +Puedes consultar más información en el [[MARKETPLACE_IMPORTS_URL] registro de errores]. + <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="OutboxUploadHadErrors"> - El envÃo al mercado ha tenido errores. Corrige los problemas de tu buzón de salida y repite la operación. Muchas gracias. - <usetemplate name="okbutton" yestext="Reintentar"/> + <notification name="OutboxImportFailed"> + Error de transferencia + +No se han enviado carpetas al Mercado a causa de un error del sistema o de la red. Vuelve a intentarlo más tarde. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxInitFailed"> + Error al inicializar el mercado + +La inicialización del mercado ha fallado por un error del sistema o de la red. Vuelve a intentarlo más tarde. + <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="CompileQueueSaveText"> Hubo un problema al subir el texto de un script por la siguiente razón: [REASON]. Por favor, inténtalo más tarde. @@ -1442,8 +1463,8 @@ Debemos reiniciar [APP_NAME] para instalar la actualización. <usetemplate ignoretext="Confirmar antes de devolver objetos a sus propietarios." name="okcancelignore" notext="Cancelar" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Actualmente, eres miembro del grupo <nolink>[GROUP]</nolink>. -¿Dejar el grupo? + Actualmente perteneces al grupo <nolink>[GROUP]</nolink>. +¿Deseas abandonar el grupo? <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> </notification> <notification name="ConfirmKick"> @@ -2823,6 +2844,18 @@ Con los siguientes residentes: [RESIDENTS] <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> </notification> + <notification name="ShareFolderConfirmation"> + Sólo puedes compartir una carpeta en cada momento. + +¿Estás seguro de que quieres compartir los elementos siguientes? + +<nolink>[ITEMS]</nolink> + +Con los siguientes Residentes: + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Aceptar"/> + </notification> <notification name="ItemsShared"> Los elementos se han compartido correctamente. </notification> diff --git a/indra/newview/skins/default/xui/es/panel_region_estate.xml b/indra/newview/skins/default/xui/es/panel_region_estate.xml index 3d0de4f083..84c1ed7686 100644 --- a/indra/newview/skins/default/xui/es/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/es/panel_region_estate.xml @@ -23,10 +23,10 @@ <check_box label="Permitir el acceso público" name="externally_visible_check"/> <button label="?" name="externally_visible_help"/> <text name="Only Allow"> - Restringir el acceso a cuentas verificadas por: + Permitir únicamente el acceso a los Residentes que: </text> - <check_box label="Información de pago aportada" name="limit_payment" tool_tip="Expulsa a los Residentes no identificados."/> - <check_box label="Verificación de la edad" name="limit_age_verified" tool_tip="Expulsa a los Residentes que no hayan verificado su edad. Más información en [SUPPORT_SITE]."/> + <check_box label="Han aportado la información de pago." name="limit_payment" tool_tip="Para poder acceder a este estado los Residentes deben haber aportado información de pago en su cuenta. Para más información, ver [SUPPORT_SITE]."/> + <check_box label="Han verificado su edad" name="limit_age_verified" tool_tip="Para poder acceder a este estado los Residentes deben haber verificado su edad. Para más información, ver [SUPPORT_SITE]."/> <check_box label="Permitir el chat de voz" name="voice_chat_check"/> <button label="?" name="voice_chat_help"/> <check_box label="Permitir el teleporte a cualquier punto" name="allow_direct_teleport"/> diff --git a/indra/newview/skins/default/xui/es/panel_script_ed.xml b/indra/newview/skins/default/xui/es/panel_script_ed.xml index 46952c6974..4c4077b96f 100644 --- a/indra/newview/skins/default/xui/es/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/es/panel_script_ed.xml @@ -22,6 +22,8 @@ <menu label="Archivo" name="File"> <menu_item_call label="Guardar" name="Save"/> <menu_item_call label="Deshacer todos los cambios" name="Revert All Changes"/> + <menu_item_call label="Cargar desde archivo..." name="LoadFromFile"/> + <menu_item_call label="Guardar en archivo..." name="SaveToFile"/> </menu> <menu label="Editar" name="Edit"> <menu_item_call label="Deshacer" name="Undo"/> diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml index 79b2c32b23..7eead3bc18 100644 --- a/indra/newview/skins/default/xui/es/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml @@ -15,7 +15,7 @@ <panel.string name="buycurrencylabel"> [AMT] L$ </panel.string> - <panel name="balance_bg"> + <panel left="-410" name="balance_bg" width="200"> <text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="20 L$"/> <button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/> <button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life" width="80"/> diff --git a/indra/newview/skins/default/xui/es/sidepanel_inventory.xml b/indra/newview/skins/default/xui/es/sidepanel_inventory.xml index 79d0cb84e8..f68dcc65e3 100644 --- a/indra/newview/skins/default/xui/es/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/es/sidepanel_inventory.xml @@ -2,47 +2,24 @@ <panel label="Cosas" name="objects panel"> <panel label="" name="sidepanel__inventory_panel"> <layout_stack name="inventory_layout_stack"> - <layout_panel name="inbox_outbox_layout_panel"> - <layout_stack name="inbox_outbox_layout_stack"> - <layout_panel name="inbox_layout_panel"> - <panel label="" name="marketplace_inbox"> - <string name="InboxLabelWithArg"> - Objetos recibidos ([NUM]) - </string> - <string name="InboxLabelNoArg"> - Objetos recibidos - </string> - <button label="Objetos recibidos" name="inbox_btn"/> - <text name="inbox_fresh_new_count"> - [NUM] nuevos - </text> - <panel tool_tip="Drag and drop items to your inventory to manage and use them"> - <text name="inbox_inventory_placeholder"> - Aquà se entregarán las compras realizadas en el mercado. - </text> - </panel> - </panel> - </layout_panel> - <layout_panel name="outbox_layout_panel"> - <panel label="" name="marketplace_outbox"> - <string name="OutboxLabelWithArg"> - Buzón de salida de comerciante ([NUM]) - </string> - <string name="OutboxLabelNoArg"> - Buzón de salida de comerciante - </string> - <button label="Buzón de salida de comerciante" name="outbox_btn"/> - <button label="" name="outbox_sync_btn" tool_tip="Poner en el escaparate de Mi Mercado"/> - <panel> - <panel name="outbox_inventory_placeholder_panel"> - <text name="outbox_inventory_placeholder_title"> - Cargando... - </text> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> + <layout_panel name="inbox_layout_panel"> + <panel label="" name="marketplace_inbox"> + <string name="InboxLabelWithArg"> + Objetos recibidos ([NUM]) + </string> + <string name="InboxLabelNoArg"> + Objetos recibidos + </string> + <button label="Objetos recibidos" name="inbox_btn"/> + <text name="inbox_fresh_new_count"> + [NUM] nuevos + </text> + <panel tool_tip="Drag and drop items to your inventory to manage and use them"> + <text name="inbox_inventory_placeholder"> + Aquà se entregarán las compras realizadas en el mercado. + </text> + </panel> + </panel> </layout_panel> </layout_stack> <panel name="button_panel"> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 2a6f32f84f..67c65c6ce9 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -171,9 +171,9 @@ Actualmente, solo se permite iniciar sesión a los empleados. Consulta www.secondlife.com/status si deseas obtener actualizaciones. </string> <string name="LoginFailedPremiumOnly"> - Se ha restringido de manera temporal el inicio de sesión en Second Life con el fin de garantizar una experiencia óptima a nuestros residentes. - -Aquellos usuarios que dispongan de cuentas gratuitas no podrán acceder a Second Life durante este perÃodo de tiempo, ya que el propósito de esta medida es obtener espacio suficiente para los residentes que hayan pagado por acceder a Second Life. + Las conexiones a Second Life se han restringido provisionalmente para garantizar que los usuarios que ya están conectados tengan la mejor experiencia posible. + +Durante este tiempo, las personas con cuentas gratuitas no podrán acceder a Second Life, ya que tienen prioridad los usuarios con una cuenta de pago. </string> <string name="LoginFailedComputerProhibited"> No se puede acceder a Second Life desde este ordenador. @@ -330,17 +330,35 @@ Intenta iniciar sesión de nuevo en unos instantes. Aquà se puede arrastrar sólo un Ãtem </string> <string name="TooltipPrice" value="[AMOUNT] L$:"/> + <string name="TooltipOutboxDragToWorld"> + No puedes colocar objetos en tu buzón de salida de comerciante + </string> <string name="TooltipOutboxNoTransfer"> - Uno o varios de estos objetos no se pueden vender o transferir a otro usuario. + Uno o varios de estos objetos no se pueden vender o transferir. + </string> + <string name="TooltipOutboxNotInInventory"> + Tu buzón de salida de comerciante sólo puede aceptar objetos procedentes directamente de tu inventario </string> <string name="TooltipOutboxWorn"> - Llevas puestos uno o más de estos objetos. QuÃtatelos del avatar y vuelve a intentar moverlos. + No puedes poner artÃculos que llevas puestos en el buzón de salida de comerciante + </string> + <string name="TooltipOutboxCallingCard"> + No puedes poner tarjetas de visita en tu buzón de salida de comerciante </string> <string name="TooltipOutboxFolderLevels"> - Esta carpeta tiene demasiados niveles de subcarpetas. Reorganiza las carpetas interiores de forma que tengas como máximo 4 niveles de profundidad (la carpeta raÃz contiene A, que contiene B, que contiene C). + La profundidad de carpetas anidadas excede de 3 + </string> + <string name="TooltipOutboxTooManyFolders"> + El número de subcarpetas de la carpeta de nivel superior excede de 20 </string> <string name="TooltipOutboxTooManyObjects"> - Esta carpeta contiene más de 200 objetos. Guarda algunos objetos en una caja para disminuir su cantidad. + El número de elementos de la carpeta de nivel superior excede de 200 + </string> + <string name="TooltipDragOntoOwnChild"> + No puedes mover una carpeta a su carpeta secundaria + </string> + <string name="TooltipDragOntoSelf"> + No puedes mover una carpeta dentro de sà misma </string> <string name="TooltipHttpUrl"> Pulsa para ver esta página web @@ -961,6 +979,9 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="choose_the_directory"> Elegir directorio </string> + <string name="script_files"> + Scripts + </string> <string name="AvatarSetNotAway"> Salir del estado ausente </string> @@ -1199,43 +1220,36 @@ Intenta iniciar sesión de nuevo en unos instantes. No tienes en tu inventario una copia de esta textura </string> <string name="InventoryInboxNoItems"> - Cuando compres un objeto o lo recibas por otra vÃa, aparecerá aquÃ, para que puedas arrastrarlo a una carpeta de tu inventario o eliminarlo si no deseas conservarlo. + Aquà aparecerán algunos de los objetos que recibas, como los regalos Premium. Después puedes arrastrarlos a tu inventario. </string> <string name="MarketplaceURL"> - http://marketplace.[DOMAIN_NAME] + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/ </string> <string name="MarketplaceURL_CreateStore"> - http://marketplace.[DOMAIN_NAME]/create_store + http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 </string> - <string name="MarketplaceURL_LearnMore"> - http://marketplace.[DOMAIN_NAME]/learn_more - </string> - <string name="InventoryOutboxCreationErrorTitle"> - Tu Buzón de salida de comerciante no está configurado correctamente + <string name="MarketplaceURL_Dashboard"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard </string> - <string name="InventoryOutboxCreationErrorTooltip"> - Error de configuración del Buzón de salida de comerciante + <string name="MarketplaceURL_Imports"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports </string> - <string name="InventoryOutboxCreationError"> - Ponte en contacto con el servicio de atención al cliente para resolver el problema. + <string name="MarketplaceURL_LearnMore"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more </string> <string name="InventoryOutboxNotMerchantTitle"> - Cualquiera puede vender objetos en el mercado - </string> - <string name="InventoryOutboxNotMerchantTooltip"> - ¡Hazte comerciante! + Cualquier usuario puede vender objetos en el mercado. </string> + <string name="InventoryOutboxNotMerchantTooltip"/> <string name="InventoryOutboxNotMerchant"> - [[MARKETPLACE_URL] El Mercado de Second Life] pone en venta más de un millón de productos virtuales, todos ellos creados por residentes. Tú también puedes vender los objetos que crees, asà como algunos de los objetos que hayas comprado. Es fácil y es gratuito. [[LEARN_MORE_URL] Más información] o [[CREATE_STORE_URL] crea una tienda] en el mercado para empezar. + Para hacerte comerciante debes [[MARKETPLACE_CREATE_STORE_URL] crear una tienda del Mercado]. </string> <string name="InventoryOutboxNoItemsTitle"> - Una nueva forma para enviar objetos al mercado - </string> - <string name="InventoryOutboxNoItemsTooltip"> - Arrastra y coloca aquà los objetos que desees preparar para venderlos en el mercado + El buzón de salida está vacÃo. </string> + <string name="InventoryOutboxNoItemsTooltip"/> <string name="InventoryOutboxNoItems"> - Arrastra a esta zona los objetos o carpetas que desees vender. Aparecerá una copia del objeto, sin quitarlo de tu inventario, salvo que el objeto arrastrado sea "no copiable". Cuando estés listo para enviar los objetos al mercado, pulsa en el botón Subir. Cuando se hayan trasladado los objetos a tu inventario en el mercado, desaparecerán de esta carpeta. + Arrastra carpetas a esta sección y pulsa en "Enviar al Mercado" para incluirlas en la lista de venta del [[MARKETPLACE_DASHBOARD_URL] Mercado]. </string> <string name="Marketplace Error None"> Sin errores @@ -4017,7 +4031,7 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. </string> <string name="uploading_abuse_report"> Subiendo... - + Denuncia de infracción </string> <string name="New Shape"> @@ -4285,7 +4299,7 @@ Denuncia de infracción <string name="server_is_down"> Parece que hay algún problema que ha escapado a nuestros controles. - Visita status.secondlifegrid.net para ver si hay alguna incidencia conocida que esté afectando al servicio. + Visita status.secondlifegrid.net para ver si hay alguna incidencia conocida que esté afectando al servicio. Si sigues teniendo problemas, comprueba la configuración de la red y del servidor de seguridad. </string> <string name="dateTimeWeekdaysNames"> @@ -4752,6 +4766,9 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas <string name="Command_Move_Label"> Caminar / Correr / Volar </string> + <string name="Command_Outbox_Label"> + Buzón de salida de comerciante + </string> <string name="Command_People_Label"> Gente </string> @@ -4824,6 +4841,9 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas <string name="Command_Move_Tooltip"> Desplazando el avatar </string> + <string name="Command_Outbox_Tooltip"> + Transfiere objetos a tu mercado para venderlos + </string> <string name="Command_People_Tooltip"> Amigos, grupos y personas próximas </string> diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml index b554a0a892..49af1a87e1 100644 --- a/indra/newview/skins/default/xui/fr/floater_about_land.xml +++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml @@ -377,7 +377,7 @@ Seules les parcelles de grande taille peuvent apparaître dans la recherche. </text> <texture_picker label="" name="snapshot_ctrl" tool_tip="Cliquez pour sélectionner une image"/> <text name="allow_label5"> - et chatter avec les avatars sur cette parcelle + Les avatars présents sur d'autres parcelles peuvent voir et chatter avec les avatars présents sur cette parcelle. </text> <check_box label="Voir les avatars" name="SeeAvatarsCheck" tool_tip="Permettre aux avatars présents sur d'autres parcelles de voir et chatter avec les avatars présents sur cette parcelle et à vous de les voir et de chatter avec eux."/> <text name="landing_point"> @@ -439,7 +439,7 @@ musique : <text name="Sound:"> Son : </text> - <check_box label="Limiter les gestes et sons d'objet à cette parcelle" name="check sound local"/> + <check_box label="Limiter les sons des gestes et des objets à cette parcelle" name="check sound local"/> <text name="Avatar Sounds:"> Sons d'avatar : </text> @@ -465,12 +465,12 @@ musique : <text name="Limit access to this parcel to:"> Accès à cette parcelle </text> - <check_box label="Autoriser l'accès public [MATURITY]" name="public_access"/> + <check_box label="Autoriser l'accès public (des lignes d'interdiction seront créées si cette case n'est pas cochée)" name="public_access"/> <text name="Only Allow"> - Limiter l'accès aux résidents vérifiés par : + Conditions d'accès des résidents : </text> - <check_box label="Informations de paiement enregistrées [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Bannir les résidents non identifiés."/> - <check_box label="Vérification de l'âge [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Bannir les résidents qui n'ont pas vérifié leur âge. Consultez la page [SUPPORT_SITE] pour plus d'informations."/> + <check_box label="Informations de paiement enregistrées [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Pour pouvoir accéder à cette parcelle, les résidents doivent avoir enregistré des informations de paiement. Consultez le [SUPPORT_SITE] pour plus d'informations."/> + <check_box label="Âge vérifié [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Pour que les résidents puissent accéder à cette parcelle, leur âge doit avoir fait l'objet d'une vérification. Consultez le [SUPPORT_SITE] pour plus d'informations."/> <check_box label="Autoriser l'accès au groupe : [GROUP]" name="GroupCheck" tool_tip="Définir le groupe à l'onglet Général."/> <check_box label="Vendre des pass à  :" name="PassCheck" tool_tip="Autoriser un accès temporaire à cette parcelle"/> <combo_box name="pass_combo" width="110"> diff --git a/indra/newview/skins/default/xui/fr/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/fr/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..e82518ce80 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_animation_anim_preview.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Anim Preview" title="ANIMATION.ANIM"> + <text name="name_label"> + Nom : + </text> + <text name="description_label"> + Description : + </text> + <button label="Charger ([AMOUNT] L$)" name="ok_btn"/> + <button label="Annuler" label_selected="Annuler" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_animation_bvh_preview.xml b/indra/newview/skins/default/xui/fr/floater_animation_bvh_preview.xml new file mode 100644 index 0000000000..84c40b5987 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_animation_bvh_preview.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Animation Preview"> + <floater.string name="failed_to_initialize"> + Échec de l'initialisation du mouvement + </floater.string> + <floater.string name="anim_too_long"> + La durée du fichier d'animation est de [LENGTH] secondes. + +La limite maximale est de [MAX_LENGTH] secondes. + </floater.string> + <floater.string name="failed_file_read"> + Impossible de lire le fichier d'animation. + +[STATUS] + </floater.string> + <floater.string name="E_ST_OK"> + Ok + </floater.string> + <floater.string name="E_ST_EOF"> + Fin prématurée du fichier. + </floater.string> + <floater.string name="E_ST_NO_CONSTRAINT"> + Impossible de lire la définition des contraintes. + </floater.string> + <floater.string name="E_ST_NO_FILE"> + Impossible d'ouvrir le fichier BVH. + </floater.string> + <floater.string name="E_ST_NO_HIER"> + En-tête HIERARCHY non valide. + </floater.string> + <floater.string name="E_ST_NO_JOINT"> + Impossible de trouver ROOT ou JOINT. + </floater.string> + <floater.string name="E_ST_NO_NAME"> + Impossible d'obtenir le nom JOINT. + </floater.string> + <floater.string name="E_ST_NO_OFFSET"> + Impossible de trouver OFFSET. + </floater.string> + <floater.string name="E_ST_NO_CHANNELS"> + CHANNELS introuvables. + </floater.string> + <floater.string name="E_ST_NO_ROTATION"> + Impossible d'obtenir l'ordre de rotation. + </floater.string> + <floater.string name="E_ST_NO_AXIS"> + Impossible d'obtenir l'axe de rotation. + </floater.string> + <floater.string name="E_ST_NO_MOTION"> + Impossible de trouver MOTION. + </floater.string> + <floater.string name="E_ST_NO_FRAMES"> + Impossible d'obtenir le nombre d'images. + </floater.string> + <floater.string name="E_ST_NO_FRAME_TIME"> + Impossible d'obtenir la durée des images. + </floater.string> + <floater.string name="E_ST_NO_POS"> + Impossible d'obtenir les valeurs de position. + </floater.string> + <floater.string name="E_ST_NO_ROT"> + Impossible d'obtenir les valeurs de rotation. + </floater.string> + <floater.string name="E_ST_NO_XLT_FILE"> + Impossible d'ouvrir le fichier de traduction. + </floater.string> + <floater.string name="E_ST_NO_XLT_HEADER"> + Impossible de lire l'en-tête de traduction. + </floater.string> + <floater.string name="E_ST_NO_XLT_NAME"> + Impossible de lire les noms de traduction. + </floater.string> + <floater.string name="E_ST_NO_XLT_IGNORE"> + Impossible de lire la valeur ignorant la traduction. + </floater.string> + <floater.string name="E_ST_NO_XLT_RELATIVE"> + Impossible de lire la valeur relative de la traduction. + </floater.string> + <floater.string name="E_ST_NO_XLT_OUTNAME"> + Impossible de lire la valeur outname de la traduction. + </floater.string> + <floater.string name="E_ST_NO_XLT_MATRIX"> + Impossible de lire la matrice de traduction. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGECHILD"> + Impossible d'obtenir le nom mergechild. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGEPARENT"> + Impossible d'obtenir le nom mergeparent. + </floater.string> + <floater.string name="E_ST_NO_XLT_PRIORITY"> + Impossible d'obtenir la valeur priority. + </floater.string> + <floater.string name="E_ST_NO_XLT_LOOP"> + Impossible d'obtenir la valeur loop. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEIN"> + Impossible d'obtenir les valeurs easeIn. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEOUT"> + Impossible d'obtenir les valeurs easeOut. + </floater.string> + <floater.string name="E_ST_NO_XLT_HAND"> + Impossible d'obtenir la valeur hand morph. + </floater.string> + <floater.string name="E_ST_NO_XLT_EMOTE"> + Impossible de lire le nom emote. + </floater.string> + <floater.string name="E_ST_BAD_ROOT"> + Nom root joint incorrect ; utiliser "hip". + </floater.string> + <text name="name_label"> + Nom : + </text> + <text name="description_label"> + Description : + </text> + <spinner label="Priorité" name="priority" tool_tip="Contrôle quelles autres animations peuvent être remplacées par cette animation."/> + <check_box label="Boucle" name="loop_check" tool_tip="Entraîne la lecture en boucle de cette animation."/> + <spinner label="Début (%)" name="loop_in_point" tool_tip="Définit le point de l'animation auquel retourne la boucle."/> + <spinner label="Fin (%)" name="loop_out_point" tool_tip="Définit le point de l'animation auquel se termine la boucle."/> + <text name="hand_label"> + Pose des mains + </text> + <combo_box name="hand_pose_combo" tool_tip="Contrôle ce que font les mains pendant l'animation."> + <combo_box.item label="Écartées" name="Spread"/> + <combo_box.item label="Détendues" name="Relaxed"/> + <combo_box.item label="Montrer du doigt (les deux)" name="PointBoth"/> + <combo_box.item label="Poing" name="Fist"/> + <combo_box.item label="Détendue (gauche)" name="RelaxedLeft"/> + <combo_box.item label="Montrer du doigt (gauche)" name="PointLeft"/> + <combo_box.item label="Poing (gauche)" name="FistLeft"/> + <combo_box.item label="Détendue (droite)" name="RelaxedRight"/> + <combo_box.item label="Montrer du doigt (droite)" name="PointRight"/> + <combo_box.item label="Poing (droite)" name="FistRight"/> + <combo_box.item label="Salut (droite)" name="SaluteRight"/> + <combo_box.item label="Clavier" name="Typing"/> + <combo_box.item label="Paix (droite)" name="PeaceRight"/> + </combo_box> + <text name="emote_label"> + Expression + </text> + <combo_box name="emote_combo" tool_tip="Contrôle ce que fait le visage pendant l'animation."> + <item label="(Aucune)" name="[None]" value=""/> + <item label="Aaaaah" name="Aaaaah" value="Aaaaah"/> + <item label="Effrayé" name="Afraid" value="Effrayé"/> + <item label="En colère" name="Angry" value="En colère"/> + <item label="Grand sourire" name="BigSmile" value="Grand sourire"/> + <item label="Ennui" name="Bored" value="Ennui"/> + <item label="Pleurer" name="Cry" value="Pleurer"/> + <item label="Mépris" name="Disdain" value="Mépris"/> + <item label="Gêne" name="Embarrassed" value="Gêne"/> + <item label="Froncer les sourcils" name="Frown" value="Froncer les sourcils"/> + <item label="Embrasser" name="Kiss" value="Embrasser"/> + <item label="Rire" name="Laugh" value="Rire"/> + <item label="Tirer la langue" name="Plllppt" value="Tirer la langue"/> + <item label="Dégoût" name="Repulsed" value="Dégoût"/> + <item label="Triste" name="Sad" value="Triste"/> + <item label="Hausser les épaules" name="Shrug" value="Hausser les épaules"/> + <item label="Sourire" name="Smile" value="Sourire"/> + <item label="Surprise" name="Surprise" value="Surprise"/> + <item label="Clin d'Å“il" name="Wink" value="Clin d'Å“il"/> + <item label="Inquiétude" name="Worry" value="Inquiétude"/> + </combo_box> + <text name="preview_label"> + Aperçu + </text> + <combo_box name="preview_base_anim" tool_tip="Permet de tester le comportement de l'animation lorsque votre avatar effectue certaines actions courantes."> + <item label="Debout" name="Standing" value="Debout"/> + <item label="En marche" name="Walking" value="En marche"/> + <item label="Assis" name="Sitting" value="Assis"/> + <item label="En vol" name="Flying" value="En vol"/> + </combo_box> + <spinner label="Transition début (s)" name="ease_in_time" tool_tip="Durée (en secondes) de l'entrée en fondu de l'animation."/> + <spinner label="Transition fin (s)" name="ease_out_time" tool_tip="Durée (en secondes) de la sortie en fondu de l'animation."/> + <button name="play_btn" tool_tip="Lire l'animation."/> + <button name="pause_btn" tool_tip="Suspendre l'animation."/> + <button name="stop_btn" tool_tip="Arrêter la lecture de l'animation."/> + <text name="bad_animation_text"> + Impossible de lire le fichier d'animation. + +Les fichiers BVH exportés depuis Poser 4 sont recommandés. + </text> + <button label="Charger ([AMOUNT] L$)" name="ok_btn"/> + <button label="Annuler" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml index c7d27c0589..890411d091 100644 --- a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="CHAT PRÈS DE MOI"> <panel name="bottom_panel"> - <line_editor label="Cliquer ici pour chatter." name="chat_box" tool_tip="Appuyer sur Entrée pour dire, Ctrl-Entrée pour crier"/> - <button name="show_nearby_chat" tool_tip="Affiche/Masque le journal de chats près de vous"/> + <line_editor label="Cliquer ici pour chatter." name="chat_box" tool_tip="Appuyer sur Entrée pour dire, Ctrl+Entrée pour crier"/> + <button name="show_nearby_chat" tool_tip="Afficher/masquer le journal de chat près de vous."/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/fr/floater_merchant_outbox.xml new file mode 100644 index 0000000000..b491dd6aed --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_merchant_outbox.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_merchant_outbox" title="BOÃŽTE D'ENVOI VENDEUR"> + <string name="OutboxFolderCount1"> + 1 dossier + </string> + <string name="OutboxFolderCountN"> + [NUM] dossiers + </string> + <string name="OutboxImporting"> + Envoi de dossiers... + </string> + <string name="OutboxInitializing"> + Initialisation... + </string> + <panel label=""> + <panel> + <panel name="outbox_inventory_placeholder_panel"> + <text name="outbox_inventory_placeholder_title"> + Chargement... + </text> + </panel> + </panel> + <panel> + <button label="Envoyer vers la Place du marché" name="outbox_import_btn" tool_tip="Vers ma vitrine de la Place du marché"/> + </panel> + </panel> +</floater> 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 63feb1d403..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="header_panel"> - <text name="header_text"> - Choisir un fichier de modèle - </text> - </panel> - <panel name="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 les chargements de modèle de maillage. - </text> - </panel> - </panel> - <panel name="optimize_panel"> - <panel name="header_panel"> - <text name="header_text"> - Optimiser le modèle - </text> - </panel> - <text name="description"> - Le modèle a été optimisé en termes de performances. Vous pouvez l'ajuster si vous le souhaitez. - </text> - <panel name="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="header_panel"> - <text name="header_text"> - Ajuster les propriétés physiques - </text> - </panel> - <text name="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="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="header_panel"> - <text name="header_text"> - Vérification - </text> - </panel> - <panel name="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="header_panel"> - <text name="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_preview_animation.xml b/indra/newview/skins/default/xui/fr/floater_preview_animation.xml index fdd2ac8beb..f2cb1d5e70 100644 --- a/indra/newview/skins/default/xui/fr/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/fr/floater_preview_animation.xml @@ -6,6 +6,6 @@ <text name="desc txt"> Description : </text> - <button label="Exécuter dans Second Life" label_selected="Stop" name="Anim play btn" tool_tip="Lire cette animation de façon à ce que les autres puissent la voir" width="131"/> - <button label="Exécuter localement" label_selected="Stop" left="160" name="Anim audition btn" tool_tip="Lire cette animation de façon à ce que vous soyez la seule personne à pouvoir la voir" width="120"/> + <button label="Exécuter dans Second Life" label_selected="Arrêter" name="Inworld" tool_tip="Lire cette animation de façon à ce que les autres la voient."/> + <button label="Exécuter localement" label_selected="Arrêter" name="Locally" tool_tip="Lire cette animation de façon à ce que vous soyez la seule personne à la voir."/> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/fr/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..b479d5f6d6 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_test_layout_stacks.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="LAYOUTSTACK TESTS"/> diff --git a/indra/newview/skins/default/xui/fr/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/fr/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..702170ef52 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_test_text_vertical_aligment.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="FLOATER TEST"/> diff --git a/indra/newview/skins/default/xui/fr/floater_tools.xml b/indra/newview/skins/default/xui/fr/floater_tools.xml index af5678ff0e..e21c6f4c08 100644 --- a/indra/newview/skins/default/xui/fr/floater_tools.xml +++ b/indra/newview/skins/default/xui/fr/floater_tools.xml @@ -1,5 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="toolbox floater" short_title="OUTILS POUR LA CONSTRUCTION" title=""> + <floater.string name="grid_screen_text"> + Écran + </floater.string> + <floater.string name="grid_local_text"> + Local + </floater.string> + <floater.string name="grid_world_text"> + Monde + </floater.string> + <floater.string name="grid_reference_text"> + Référence + </floater.string> + <floater.string name="grid_attachment_text"> + Élément attaché + </floater.string> <floater.string name="status_rotate"> Pour faire tourner l'objet, faites glisser les bandes de couleur. </floater.string> @@ -63,7 +78,12 @@ </text> <check_box initial_value="true" label="Étirer les textures" name="checkbox stretch textures"/> <check_box initial_value="true" label="Fixer" name="checkbox snap to grid"/> - <button label="Options..." label_selected="Options..." name="Options..." tool_tip="Afficher d'autres options de grille"/> + <combo_box name="combobox grid mode" tool_tip="Choisir le type d'axe de grille pour le positionnement de l'objet."> + <combo_box.item label="Monde" name="World"/> + <combo_box.item label="Local" name="Local"/> + <combo_box.item label="Référence" name="Reference"/> + </combo_box> + <button label="" label_selected="Options..." name="Options..." tool_tip="Afficher d'autres options de grille"/> <button label="" label_selected="" name="ToolCube" tool_tip="Cube"/> <button label="" label_selected="" name="ToolPrism" tool_tip="Prisme droit"/> <button label="" label_selected="" name="ToolPyramid" tool_tip="Pyramide"/> @@ -106,7 +126,7 @@ Aucune sélection effectuée. </text> <text name="remaining_capacity"> - [CAPACITY_STRING] [secondlife:///app/openfloater/object_weights Plus d'infos] + [CAPACITY_STRING] [secondlife:///app/openfloater/object_weights Plus d'infos] </text> <tab_container name="Object Info Tabs"> <panel label="Général" name="General"> diff --git a/indra/newview/skins/default/xui/fr/floater_voice_effect.xml b/indra/newview/skins/default/xui/fr/floater_voice_effect.xml index 92ee6ecf24..671fb5c14d 100644 --- a/indra/newview/skins/default/xui/fr/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/fr/floater_voice_effect.xml @@ -42,13 +42,16 @@ <string name="effect_Demon"> Démon </string> + <string name="effect_Female Elf"> + Femme elfe + </string> <string name="effect_Flirty"> Flirt </string> <string name="effect_Foxy"> Séduction </string> - <string name="effect_Halloween_2010_Bonus"> + <string name="effect_Halloween 2010 Bonus"> Halloween_2010_Bonus </string> <string name="effect_Helium"> @@ -57,9 +60,18 @@ <string name="effect_Husky"> Rauque </string> + <string name="effect_Husky Whisper"> + Murmure rauque + </string> <string name="effect_Intercom"> Interphone </string> + <string name="effect_Julia"> + Julia + </string> + <string name="effect_Lo Lilt"> + Mélodieux + </string> <string name="effect_Macho"> Macho </string> @@ -69,6 +81,9 @@ <string name="effect_Mini"> Mini </string> + <string name="effect_Model"> + Modèle + </string> <string name="effect_Nano"> Nano </string> @@ -90,6 +105,9 @@ <string name="effect_Roxanne"> Roxanne </string> + <string name="effect_Rumble"> + Grondement + </string> <string name="effect_Sabrina"> Sabrina </string> @@ -102,6 +120,9 @@ <string name="effect_Shorty"> Petite voix </string> + <string name="effect_Smaller"> + Plus faible + </string> <string name="effect_Sneaky"> Sournois </string> diff --git a/indra/newview/skins/default/xui/fr/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/fr/menu_inspect_object_gear.xml index 074bb54cdc..f3b974aba5 100644 --- a/indra/newview/skins/default/xui/fr/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/fr/menu_inspect_object_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<menu name="Gear Menu"> +<toggleable_menu name="Gear Menu"> <menu_item_call label="Toucher" name="touch"/> <menu_item_call label="M'asseoir" name="sit"/> <menu_item_call label="Payer" name="pay"/> @@ -12,7 +12,8 @@ <menu_item_call label="Ajouter" name="add"/> <menu_item_call label="Signaler" name="report"/> <menu_item_call label="Ignorer" name="block"/> + <menu_item_call label="Ne plus ignorer" name="unblock"/> <menu_item_call label="Zoomer en avant" name="zoom_in"/> <menu_item_call label="Supprimer" name="remove"/> <menu_item_call label="En savoir plus" name="more_info"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_inventory.xml b/indra/newview/skins/default/xui/fr/menu_inventory.xml index 403111c4de..59dcff9075 100644 --- a/indra/newview/skins/default/xui/fr/menu_inventory.xml +++ b/indra/newview/skins/default/xui/fr/menu_inventory.xml @@ -59,6 +59,7 @@ <menu_item_call label="Propriétés" name="Properties"/> <menu_item_call label="Renommer" name="Rename"/> <menu_item_call label="Copier l'UUID (identifiant universel unique)" name="Copy Asset UUID"/> + <menu_item_call label="Couper" name="Cut"/> <menu_item_call label="Copier" name="Copy"/> <menu_item_call label="Coller" name="Paste"/> <menu_item_call label="Coller comme lien" name="Paste As Link"/> @@ -84,6 +85,6 @@ <menu_item_call label="Ajouter" name="Wearable Add"/> <menu_item_call label="Enlever" name="Take Off"/> <menu_item_call label="Copier vers la boîte d'envoi vendeur" name="Merchant Copy"/> - <menu_item_call label="Déplacer vers la boîte d'envoi vendeur" name="Merchant Move"/> + <menu_item_call label="Envoyer vers la Place du marché" name="Marketplace Send"/> <menu_item_call label="--aucune option--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/fr/menu_login.xml b/indra/newview/skins/default/xui/fr/menu_login.xml index 8210c1be51..dc6b2793ca 100644 --- a/indra/newview/skins/default/xui/fr/menu_login.xml +++ b/indra/newview/skins/default/xui/fr/menu_login.xml @@ -17,8 +17,8 @@ <menu_item_call label="Définir la taille de la fenêtre..." name="Set Window Size..."/> <menu_item_call label="Afficher les conditions d'utilisation" name="TOS"/> <menu_item_call label="Afficher le message critique" name="Critical"/> - <menu_item_call label="Test du navigateur de médias" name="Web Browser Test"/> <menu_item_call label="Test de débogage de la fenêtre flottante du contenu Web" name="Web Content Floater Debug Test"/> + <menu label="Définir le niveau de connexion" name="Set Logging Level"/> <menu_item_check label="Afficher le sélecteur de grille" name="Show Grid Picker"/> <menu_item_call label="Afficher la console des notifications" name="Show Notifications Console"/> </menu> diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml index 9303815c30..3c3d4f5f69 100644 --- a/indra/newview/skins/default/xui/fr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml @@ -14,14 +14,14 @@ <menu_item_check label="Voler" name="Fly"/> <menu_item_check label="Toujours courir" name="Always Run"/> <menu_item_call label="Arrêter mon animation" name="Stop Animating My Avatar"/> + <menu_item_call label="Marcher / Courir / Voler..." name="Walk / run / fly"/> </menu> <menu label="Statut" name="Status"> <menu_item_call label="Absent" name="Set Away"/> <menu_item_call label="Occupé" name="Set Busy"/> </menu> - <menu_item_call label="Demander le statut Admin" name="Request Admin Options"/> - <menu_item_call label="Quitter le statut Admin" name="Leave Admin Options"/> - <menu_item_call label="Acheter des L$" name="Buy and Sell L$"/> + <menu_item_call label="Acheter des L$..." name="Buy and Sell L$"/> + <menu_item_call label="Boîte d'envoi vendeur..." name="MerchantOutbox"/> <menu_item_call label="Page d'accueil du compte..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=fr"/> </menu_item_call> @@ -63,7 +63,7 @@ <menu_item_check label="Propriétés de la parcelle" name="Parcel Properties"/> <menu_item_check label="Menu Avancé" name="Show Advanced Menu"/> </menu> - <menu label="Luminosité" name="Environment Settings"> + <menu label="Luminosité" name="Sun"> <menu_item_call label="Aube" name="Sunrise"/> <menu_item_call label="Milieu de journée" name="Noon"/> <menu_item_call label="Coucher de soleil" name="Sunset"/> @@ -178,22 +178,22 @@ <menu_item_check label="Afficher le réticule de la vue subjective" name="ShowCrosshairs"/> </menu> <menu label="Types de rendu" name="Rendering Types"> - <menu_item_check label="Simple" name="Simple"/> - <menu_item_check label="Alpha" name="Alpha"/> - <menu_item_check label="Arbre" name="Tree"/> - <menu_item_check label="Avatars" name="Character"/> - <menu_item_check label="Patch de surface" name="Surface Patch"/> - <menu_item_check label="Ciel" name="Sky"/> - <menu_item_check label="Eau" name="Water"/> - <menu_item_check label="Sol" name="Ground"/> - <menu_item_check label="Volume" name="Volume"/> - <menu_item_check label="Herbe" name="Grass"/> - <menu_item_check label="Nuages" name="Clouds"/> - <menu_item_check label="Particules" name="Particles"/> - <menu_item_check label="Placage de relief" name="Bump"/> + <menu_item_check label="Simple" name="Rendering Type Simple"/> + <menu_item_check label="Alpha" name="Rendering Type Alpha"/> + <menu_item_check label="Arbre" name="Rendering Type Tree"/> + <menu_item_check label="Avatars" name="Rendering Type Character"/> + <menu_item_check label="Patch de surface" name="Rendering Type Surface Patch"/> + <menu_item_check label="Ciel" name="Rendering Type Sky"/> + <menu_item_check label="Eau" name="Rendering Type Water"/> + <menu_item_check label="Sol" name="Rendering Type Ground"/> + <menu_item_check label="Volume" name="Rendering Type Volume"/> + <menu_item_check label="Herbe" name="Rendering Type Grass"/> + <menu_item_check label="Nuages" name="Rendering Type Clouds"/> + <menu_item_check label="Particules" name="Rendering Type Particles"/> + <menu_item_check label="Placage de relief" name="Rendering Type Bump"/> </menu> <menu label="Fonctionnalités de rendu" name="Rendering Features"> - <menu_item_check label="Interface" name="UI"/> + <menu_item_check label="Interface" name="ToggleUI"/> <menu_item_check label="Sélection" name="Selected"/> <menu_item_check label="En surbrillance" name="Highlighted"/> <menu_item_check label="Textures dynamiques" name="Dynamic Textures"/> @@ -207,8 +207,6 @@ <menu_item_check label="Effet de lissage de la souris" name="Mouse Smoothing"/> <menu_item_call label="Libérer les touches" name="Release Keys"/> <menu label="Raccourcis" name="Shortcuts"> - <menu_item_call label="Image ([COST] L$)..." name="Upload Image"/> - <menu_item_check label="Rechercher" name="Search"/> <menu_item_check label="Afficher le menu Avancé - raccourci existant" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Fermer la fenêtre" name="Close Window"/> <menu_item_call label="Fermer toutes les fenêtres" name="Close All Windows"/> @@ -217,13 +215,6 @@ <menu_item_check label="Joystick Flycam" name="Joystick Flycam"/> <menu_item_call label="Réinitialiser la vue" name="Reset View"/> <menu_item_call label="Regarder la dernière conversation" name="Look at Last Chatter"/> - <menu label="Sélectionner un outil de construction" name="Select Tool"> - <menu_item_call label="Outil de mise au point" name="Focus"/> - <menu_item_call label="Outil de déplacement" name="Move"/> - <menu_item_call label="Outil de modification" name="Edit"/> - <menu_item_call label="Outil de création" name="Create"/> - <menu_item_call label="Outil Terrain" name="Land"/> - </menu> <menu_item_call label="Zoomer en avant" name="Zoom In"/> <menu_item_call label="Zoom par défaut" name="Zoom Default"/> <menu_item_call label="Zoomer en arrière" name="Zoom Out"/> @@ -296,6 +287,7 @@ <menu_item_check label="Rayons" name="Raycast"/> <menu_item_check label="Vecteurs de vent" name="Wind Vectors"/> <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> <menu label="Rendu" name="Rendering"> @@ -337,9 +329,8 @@ <menu_item_call label="Commencer l'enregistrement" name="Start Record"/> <menu_item_call label="Arrêter l'enregistrement" name="Stop Record"/> </menu> - <menu label="Monde" name="World"> + <menu label="Monde" name="DevelopWorld"> <menu_item_check label="Ignorer les paramètres du soleil de la sim" name="Sim Sun Override"/> - <menu_item_check label="Balise animée" name="Cheesy Beacon"/> <menu_item_check label="Météo fixe" name="Fixed Weather"/> <menu_item_call label="Vidage de cache d'objet de la région" name="Dump Region Object Cache"/> </menu> @@ -371,11 +362,11 @@ </menu> <menu label="Avatar" name="Character"> <menu label="Récupérer la texture fixée" name="Grab Baked Texture"> - <menu_item_call label="Iris" name="Iris"/> - <menu_item_call label="Tête" name="Head"/> - <menu_item_call label="Haut du corps" name="Upper Body"/> - <menu_item_call label="Bas du corps" name="Lower Body"/> - <menu_item_call label="Jupe" name="Skirt"/> + <menu_item_call label="Iris" name="Grab Iris"/> + <menu_item_call label="Tête" name="Grab Head"/> + <menu_item_call label="Haut du corps" name="Grab Upper Body"/> + <menu_item_call label="Bas du corps" name="Grab Lower Body"/> + <menu_item_call label="Jupe" name="Grab Skirt"/> </menu> <menu label="Tests personnages" name="Character Tests"> <menu_item_call label="Apparence dans XML" name="Appearance To XML"/> @@ -403,20 +394,28 @@ <menu_item_check label="Textures HTTP" name="HTTP Textures"/> <menu_item_check label="Inventaire HTTP" name="HTTP Inventory"/> <menu_item_call label="Compresser les images" name="Compress Images"/> + <menu_item_call label="Activer Visual Leak Detector" name="Enable Visual Leak Detector"/> <menu_item_check label="Output Debug Minidump" name="Output Debug Minidump"/> <menu_item_check label="Console Window on next Run" name="Console Window"/> + <menu label="Définir le niveau de connexion" name="Set Logging Level"> + <menu_item_check label="Débogage" name="Debug"/> + <menu_item_check label="Infos" name="Info"/> + <menu_item_check label="Avertissement" name="Warning"/> + <menu_item_check label="Erreur" name="Error"/> + <menu_item_check label="Aucun" name="None"/> + </menu> <menu_item_call label="Demander le statut Admin" name="Request Admin Options"/> <menu_item_call label="Quitter le statut Admin" name="Leave Admin Options"/> <menu_item_check label="Afficher le menu Admin" name="View Admin Options"/> </menu> <menu label="Admin" name="Admin"> - <menu label="Object"> - <menu_item_call label="Prendre une copie" name="Take Copy"/> - <menu_item_call label="Téléporter le propriétaire" name="Force Owner To Me"/> + <menu label="Objet" name="AdminObject"> + <menu_item_call label="Prendre une copie" name="Admin Take Copy"/> + <menu_item_call label="Me faire devenir propriétaire" name="Force Owner To Me"/> <menu_item_call label="Forcer la permission du propriétaire" name="Force Owner Permissive"/> <menu_item_call label="Supprimer" name="Delete"/> <menu_item_call label="Verrouiller" name="Lock"/> - <menu_item_call label="Obtenir les ID d'actifs" name="Get Assets IDs"/> + <menu_item_call label="Obtenir les ID des actifs" name="Get Assets IDs"/> </menu> <menu label="Parcelle" name="Parcel"> <menu_item_call label="Téléporter le propriétaire" name="Owner To Me"/> @@ -447,10 +446,10 @@ <menu_item_call label="Propriétés physiques" name="Physics"/> <menu_item_call label="Tous les habits" name="All Clothes"/> </menu> - <menu label="Aide" name="Help"> + <menu label="Aide" name="DeprecatedHelp"> <menu_item_call label="Blog officiel des Linden" name="Official Linden Blog"/> <menu_item_call label="Portail d'écriture de scripts" name="Scripting Portal"/> - <menu label="Signaler des bugs" name="Bug Reporting"> + <menu label="Signaler un bug" name="Bug Reporting"> <menu_item_call label="JIRA" name="Public Issue Tracker"/> <menu_item_call label="Aide du JIRA" name="Publc Issue Tracker Help"/> <menu_item_call label="Comment signaler des bugs" name="Bug Reporing 101"/> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index 2f9bf23bc4..746a4b1d55 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -86,16 +86,37 @@ Veuillez vérifier votre connexion Internet. <usetemplate canceltext="Cancel" name="yesnocancelbuttons" notext="Ne pas enregistrer" yestext="Enregistrer"/> </notification> <notification name="ConfirmNoCopyToOutbox"> - Vous n'êtes pas autorisé à copier cet article dans la boîte d'envoi vers la Place du marché. Voulez-vous vraiment déplacer l'article suivant ? - [ITEM_NAME] - <usetemplate name="okcancelbuttons" notext="Non" yestext="Oui"/> + Vous n'êtes pas autorisé à copier un ou plusieurs de ces articles dans la boîte d'envoi vendeur. Vous pouvez les déplacer ou les laisser. + <usetemplate name="okcancelbuttons" notext="Ne pas déplacer les articles" yestext="Déplacer les articles"/> + </notification> + <notification name="OutboxFolderCreated"> + Un nouveau dossier a été créé pour chaque article que vous avez transféré vers le niveau supérieur de votre boîte d'envoi vendeur. + <usetemplate ignoretext="Un nouveau dossier a été créé dans la boîte d'envoi vendeur." name="okignore" yestext="OK"/> </notification> - <notification name="OutboxUploadComplete"> - Chargement sur la Place du marché terminé. - <usetemplate name="okbutton" yestext="Hourra !"/> + <notification name="OutboxImportComplete"> + Transfert réussi + +Tous les dossiers ont été envoyés vers la Place du marché. + <usetemplate ignoretext="Tous les dossiers envoyés vers la Place du marché" name="okignore" yestext="OK"/> </notification> - <notification name="OutboxUploadHadErrors"> - Chargement sur la Place du marché effectué avec des erreurs ! Corrigez les problèmes dans votre boîte d'envoi et réessayez. Merci ! + <notification name="OutboxImportHadErrors"> + Impossible de transférer certains dossiers + +Des erreurs se sont produites lors de l'envoi de certains dossiers vers la Place du marché. Ces dossiers sont toujours disponibles dans votre boîte d'envoi vendeur. + +Pour plus d'informations, consultez le [[MARKETPLACE_IMPORTS_URL] journal des erreurs]. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxImportFailed"> + Échec de transfert + +Aucun dossier n'a été envoyé vers la Place du marché en raison d'une erreur système ou réseau. Veuillez réessayer ultérieurement. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxInitFailed"> + Échec d'initialisation de la Place du marché + +L'initialisation de la Place du marché a échoué en raison d'une erreur système ou réseau. Veuillez réessayer ultérieurement. <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="CompileQueueSaveText"> @@ -648,7 +669,7 @@ Assurez-vous que le fichier a l'extension correcte. Impossible de créer le fichier de sortie : [FILE] </notification> <notification name="DoNotSupportBulkAnimationUpload"> - Actuellement, [APP_NAME] ne prend pas en charge le chargement de lots de fichiers d'animation. + Actuellement, [APP_NAME] ne prend pas en charge le chargement par lot de fichiers d'animation au format BVH. </notification> <notification name="CannotUploadReason"> Impossible de charger [FILE] suite au problème suivant : [REASON] @@ -1434,7 +1455,7 @@ Version [VERSION] </notification> <notification name="GroupLeaveConfirmMember"> Vous êtes actuellement membre du groupe <nolink>[GROUP]</nolink>. -Quitter le groupe ? +Quitter le groupe ? <usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/> </notification> <notification name="ConfirmKick"> @@ -2609,16 +2630,16 @@ Accepter cette requête ? <nolink>[TITLE]</nolink> de [NAME] [MESSAGE] <form name="form"> - <button name="Mute" text="Ignorer"/> - <button name="Ignore" text="Ignorer"/> + <button name="Client_Side_Mute" text="Bloquer"/> + <button name="Client_Side_Ignore" text="Ignorer"/> </form> </notification> <notification name="ScriptDialogGroup"> <nolink>[TITLE]</nolink> de [GROUPNAME] [MESSAGE] <form name="form"> - <button name="Mute" text="Ignorer"/> - <button name="Ignore" text="Ignorer"/> + <button name="Client_Side_Mute" text="Bloquer"/> + <button name="Client_Side_Ignore" text="Ignorer"/> </form> </notification> <notification name="BuyLindenDollarSuccess"> @@ -2816,6 +2837,18 @@ avec les résidents suivants : [RESIDENTS] ? <usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/> </notification> + <notification name="ShareFolderConfirmation"> + Vous ne pouvez partager qu'un dossier à la fois. + +Voulez-vous vraiment partager les articles suivants : + +<nolink>[ITEMS]</nolink> + +avec les résidents suivants : + +[RESIDENTS] ? + <usetemplate name="okcancelbuttons" notext="Annuler" yestext="Ok"/> + </notification> <notification name="ItemsShared"> Articles partagés. </notification> diff --git a/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml b/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml index 00bd6e81ae..b02e53269b 100644 --- a/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="nearby_chat"> - <check_box label="Traduire le chat" name="translate_chat_checkbox"/> + <layout_stack name="stack"> + <layout_panel name="translate_chat_checkbox_lp"> + <check_box label="Traduire le chat" name="translate_chat_checkbox"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/fr/panel_region_estate.xml b/indra/newview/skins/default/xui/fr/panel_region_estate.xml index fb650ff646..9d97d1bf29 100644 --- a/indra/newview/skins/default/xui/fr/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/fr/panel_region_estate.xml @@ -18,10 +18,10 @@ domaine. (inconnu) </text> <text name="Only Allow"> - Limiter l'accès aux comptes vérifiés par : + Conditions d'accès des résidents : </text> - <check_box label="Infos de paiement enregistrées" name="limit_payment" tool_tip="Bannir les résidents non identifiés"/> - <check_box label="Vérification de l'âge" name="limit_age_verified" tool_tip="Bannir les résidents qui n'ont pas vérifié leur âge. Consultez la page [SUPPORT_SITE] pour plus d'informations."/> + <check_box label="Informations de paiement enregistrées" name="limit_payment" tool_tip="Pour pouvoir accéder à ce domaine, les résidents doivent avoir enregistré des informations de paiement. Consultez le [SUPPORT_SITE] pour plus d'informations."/> + <check_box label="Âge vérifié" name="limit_age_verified" tool_tip="Pour que les résidents puissent accéder à ce domaine, leur âge doit avoir fait l'objet d'une vérification. Consultez le [SUPPORT_SITE] pour plus d'informations."/> <check_box label="Autoriser les chats vocaux" name="voice_chat_check"/> <button label="?" name="voice_chat_help"/> <text name="abuse_email_text"> diff --git a/indra/newview/skins/default/xui/fr/panel_script_ed.xml b/indra/newview/skins/default/xui/fr/panel_script_ed.xml index 2b08ae56c5..29fbe3c7e7 100644 --- a/indra/newview/skins/default/xui/fr/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/fr/panel_script_ed.xml @@ -22,6 +22,8 @@ <menu label="Fichier" name="File"> <menu_item_call label="Enregistrer" name="Save"/> <menu_item_call label="Annuler tous les changements" name="Revert All Changes"/> + <menu_item_call label="Charger depuis un fichier..." name="LoadFromFile"/> + <menu_item_call label="Enregistrer sous..." name="SaveToFile"/> </menu> <menu label="Modifier" name="Edit"> <menu_item_call label="Annuler" name="Undo"/> diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml index c0d59a3182..ba36a7d299 100644 --- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml @@ -15,7 +15,7 @@ <panel.string name="buycurrencylabel"> [AMT] L$ </panel.string> - <panel name="balance_bg"> + <panel left="-405" name="balance_bg" width="195"> <text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="20 L$"/> <button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/> <button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/> diff --git a/indra/newview/skins/default/xui/fr/sidepanel_inventory.xml b/indra/newview/skins/default/xui/fr/sidepanel_inventory.xml index 969bd1ac44..1b9c832679 100644 --- a/indra/newview/skins/default/xui/fr/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/fr/sidepanel_inventory.xml @@ -2,47 +2,24 @@ <panel label="Choses" name="objects panel"> <panel label="" name="sidepanel__inventory_panel"> <layout_stack name="inventory_layout_stack"> - <layout_panel name="inbox_outbox_layout_panel"> - <layout_stack name="inbox_outbox_layout_stack"> - <layout_panel name="inbox_layout_panel"> - <panel label="" name="marketplace_inbox"> - <string name="InboxLabelWithArg"> - Articles reçus ([NUM]) - </string> - <string name="InboxLabelNoArg"> - Articles reçus - </string> - <button label="Articles reçus" name="inbox_btn"/> - <text name="inbox_fresh_new_count"> - [NUM] nouv. - </text> - <panel tool_tip="Drag and drop items to your inventory to manage and use them"> - <text name="inbox_inventory_placeholder"> - Ici seront livrés les achats effectués sur la Place du marché. - </text> - </panel> - </panel> - </layout_panel> - <layout_panel name="outbox_layout_panel"> - <panel label="" name="marketplace_outbox"> - <string name="OutboxLabelWithArg"> - Boîte d'envoi vendeur ([NUM]) - </string> - <string name="OutboxLabelNoArg"> - Boîte d'envoi vendeur - </string> - <button label="Boîte d'envoi vendeur" name="outbox_btn"/> - <button label="" name="outbox_sync_btn" tool_tip="Vers ma vitrine de la Place du marché"/> - <panel> - <panel name="outbox_inventory_placeholder_panel"> - <text name="outbox_inventory_placeholder_title"> - Chargement... - </text> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> + <layout_panel name="inbox_layout_panel"> + <panel label="" name="marketplace_inbox"> + <string name="InboxLabelWithArg"> + Articles reçus ([NUM]) + </string> + <string name="InboxLabelNoArg"> + Articles reçus + </string> + <button label="Articles reçus" name="inbox_btn"/> + <text name="inbox_fresh_new_count"> + [NUM] nouv. + </text> + <panel name="inbox_inventory_placeholder_panel" tool_tip="Glisser-déposer des articles dans votre inventaire pour les utiliser."> + <text name="inbox_inventory_placeholder"> + Ici seront livrés les achats effectués sur la Place du marché. + </text> + </panel> + </panel> </layout_panel> </layout_stack> <panel name="button_panel"> diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index d959a96565..8b410128da 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -181,8 +181,8 @@ Consultez la page www.secondlife.com/status pour plus d'informations. </string> <string name="LoginFailedPremiumOnly"> Les connexions à Second Life sont temporairement limitées afin de s'assurer que l'expérience des utilisateurs présents dans le monde virtuel soit optimale. - -Les personnes disposant de comptes gratuits ne pourront pas accéder à Second Life pendant ce temps afin de permettre à celles qui ont payé pour pouvoir utiliser Second Life puissent le faire. + +Les personnes disposant de comptes gratuits ne pourront pas accéder à Second Life pendant ce temps afin de permettre à celles qui ont payé pour pouvoir utiliser Second Life de le faire. </string> <string name="LoginFailedComputerProhibited"> Impossible d'accéder à Second Life depuis cet ordinateur. @@ -339,17 +339,35 @@ Veuillez réessayer de vous connecter dans une minute. Impossible de faire glisser plus d'un objet ici </string> <string name="TooltipPrice" value="[AMOUNT] L$ :"/> + <string name="TooltipOutboxDragToWorld"> + Impossible de rezzer des articles dans la boîte d'envoi vendeur + </string> <string name="TooltipOutboxNoTransfer"> - Impossible de vendre ou de transférer un ou plusieurs de ces objets à un autre utilisateur. + Impossible de vendre ou de transférer un ou plusieurs de ces objets. + </string> + <string name="TooltipOutboxNotInInventory"> + La boîte d'envoi vendeur n'accepte que les articles directement issus de votre inventaire. </string> <string name="TooltipOutboxWorn"> - Vous portez un ou plusieurs de ces objets. Retirez-les de votre avatar, puis réessayez de les déplacer. + Impossible de placer des articles que vous portez dans votre boîte d'envoi vendeur + </string> + <string name="TooltipOutboxCallingCard"> + Impossible de placer des cartes de visite dans votre boîte d'envoi vendeur </string> <string name="TooltipOutboxFolderLevels"> - Trop de niveaux de sous-dossiers dans ce dossier. Réorganisez-le de sorte qu'un maximum de 4 niveaux soit utilisé (dossier racine contenant A contenant B contenant C). + Il existe plus de 3 niveaux de dossiers imbriqués. + </string> + <string name="TooltipOutboxTooManyFolders"> + Le dossier de niveau supérieur contient plus de 20 sous-dossiers. </string> <string name="TooltipOutboxTooManyObjects"> - Ce dossier contient plus de 200 objets. Regroupez une partie des articles dans un paquet afin de réduire le nombre d'objets. + Le dossier de niveau supérieur contient plus de 200 articles. + </string> + <string name="TooltipDragOntoOwnChild"> + Impossible de déplacer un dossier vers son enfant + </string> + <string name="TooltipDragOntoSelf"> + Impossible de déplacer un dossier vers lui-même </string> <string name="TooltipHttpUrl"> Cliquez pour afficher cette page web @@ -817,6 +835,9 @@ Veuillez réessayer de vous connecter dans une minute. <string name="anim_yes_head"> Oui </string> + <string name="multiple_textures"> + Multiples + </string> <string name="texture_loading"> Chargement... </string> @@ -976,6 +997,9 @@ Veuillez réessayer de vous connecter dans une minute. <string name="choose_the_directory"> Choisir le répertoire </string> + <string name="script_files"> + Scripts + </string> <string name="AvatarSetNotAway"> Présent </string> @@ -1214,43 +1238,36 @@ Veuillez réessayer de vous connecter dans une minute. Vous n'avez pas de copie de cette texture dans votre inventaire </string> <string name="InventoryInboxNoItems"> - Lorsque vous achetez ou recevez un article, il s'affiche ici. Vous pouvez alors le faire glisser vers un dossier de votre inventaire ou le supprimer si vous ne souhaitez pas le conserver. + Les achats que vous avez effectués sur la Place du marché s'affichent ici. Vous pouvez alors les faire glisser vers votre inventaire afin de les utiliser. </string> <string name="MarketplaceURL"> - http://marketplace.[DOMAIN_NAME] + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/ </string> <string name="MarketplaceURL_CreateStore"> - http://marketplace.[DOMAIN_NAME]/create_store + http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 </string> - <string name="MarketplaceURL_LearnMore"> - http://marketplace.[DOMAIN_NAME]/learn_more - </string> - <string name="InventoryOutboxCreationErrorTitle"> - Configuration incorrecte de votre boîte d'envoi vendeur + <string name="MarketplaceURL_Dashboard"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard </string> - <string name="InventoryOutboxCreationErrorTooltip"> - Erreur de configuration de la boîte d'envoi vendeur + <string name="MarketplaceURL_Imports"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports </string> - <string name="InventoryOutboxCreationError"> - Veuillez contacter le service clientèle pour résoudre le problème. + <string name="MarketplaceURL_LearnMore"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more </string> <string name="InventoryOutboxNotMerchantTitle"> - Tout le monde peut vendre des articles sur la Place du marché - </string> - <string name="InventoryOutboxNotMerchantTooltip"> - Devenez vendeur ! + Tout le monde peut vendre des articles sur la Place du marché. </string> + <string name="InventoryOutboxNotMerchantTooltip"/> <string name="InventoryOutboxNotMerchant"> - [[MARKETPLACE_URL] La Place du marché Second Life] comprend plus d'un million de produits virtuels à vendre, tous créés par des résidents. Vous aussi pouvez vendre les articles que vous créez, ainsi que certains articles que vous avez achetés. Le processus est simple et la configuration gratuite. [[LEARN_MORE_URL] En savoir plus] ou [[CREATE_STORE_URL] créer une boutique] sur la Place du marché pour démarrer + Pour devenir vendeur, vous devez [[MARKETPLACE_CREATE_STORE_URL] créer une boutique sur la Place du marché]. </string> <string name="InventoryOutboxNoItemsTitle"> - Un nouveau moyen d'envoyer des articles sur la Place du marché - </string> - <string name="InventoryOutboxNoItemsTooltip"> - Glisser-déposer des articles ici afin de les préparer à la vente sur la Place du marché. + Votre boîte d'envoi est vide. </string> + <string name="InventoryOutboxNoItemsTooltip"/> <string name="InventoryOutboxNoItems"> - Faites glisser les articles ou dossiers d'articles à vendre dans cette zone. Une copie de l'article s'affiche, sans que votre inventaire ne soit modifié, sauf si vous avez fait glisser un article pour lequel la copie est interdite. Une fois prêt à envoyer les articles vers la Place du marché, cliquez sur le bouton Charger. Les articles disparaissent de ce dossier lorsqu'ils ont été déplacés vers l'inventaire de la Place du marché. + Pour mettre des dossiers en vente sur la [[MARKETPLACE_DASHBOARD_URL] Place du marché], faites-les glisser vers cette zone et cliquez sur "Envoyer vers la Place du marché". </string> <string name="Marketplace Error None"> Aucune erreur @@ -3907,6 +3924,9 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE]. <string name="Saved_message"> (Enregistrement : [LONG_TIMESTAMP]) </string> + <string name="IM_unblock_only_groups_friends"> + Pour afficher ce message, vous devez désactiver la case Seuls mes amis et groupes peuvent m'appeler ou m'envoyer un IM, sous Préférences/Confidentialité. + </string> <string name="answered_call"> Votre appel a fait l'objet d'une réponse </string> @@ -4103,9 +4123,9 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE]. En ligne </string> <string name="uploading_abuse_report"> - Chargement en cours... + Chargement... -de l'infraction signalée +du rapport d'infraction </string> <string name="New Shape"> Nouvelle silhouette @@ -4372,7 +4392,7 @@ de l'infraction signalée <string name="server_is_down"> Malgré nos efforts, une erreur inattendue s'est produite. - Veuillez vous reporter à status.secondlifegrid.net afin de déterminer si un problème connu existe avec ce service. + Veuillez vous reporter à status.secondlifegrid.net afin de déterminer si un problème connu existe avec ce service. Si le problème persiste, vérifiez la configuration de votre réseau et de votre pare-feu. </string> <string name="dateTimeWeekdaysNames"> @@ -4489,7 +4509,7 @@ Essayez avec le chemin d'accès à l'éditeur entre guillemets doubles Backsp </string> <string name="Shift"> - Shift + Maj </string> <string name="Ctrl"> Ctrl @@ -4839,6 +4859,9 @@ Essayez avec le chemin d'accès à l'éditeur entre guillemets doubles <string name="Command_Move_Label"> Marcher / Courir / Voler </string> + <string name="Command_Outbox_Label"> + Boîte d'envoi vendeur + </string> <string name="Command_People_Label"> Personnes </string> @@ -4911,6 +4934,9 @@ Essayez avec le chemin d'accès à l'éditeur entre guillemets doubles <string name="Command_Move_Tooltip"> Faire bouger votre avatar </string> + <string name="Command_Outbox_Tooltip"> + Transférer des articles vers votre place de marché afin de les vendre. + </string> <string name="Command_People_Tooltip"> Amis, groupes et personnes près de vous </string> diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml index 528cf185fc..cfc3ad8fdb 100644 --- a/indra/newview/skins/default/xui/it/floater_about_land.xml +++ b/indra/newview/skins/default/xui/it/floater_about_land.xml @@ -378,7 +378,7 @@ Solamente terreni più grandi possono essere abilitati nella ricerca. </text> <texture_picker label="" name="snapshot_ctrl" tool_tip="Clicca per scegliere una immagine"/> <text name="allow_label5"> - e chattare con avatar in questo lotto + Gli avatar su altri lotti possono vedere gli avatar su questo lotto e chattare con loro </text> <check_box label="Vedi avatar" name="SeeAvatarsCheck" tool_tip="Consente ad avatar in altri lotti di vedere e chattare con avatar in questo lotto e viceversa."/> <text name="landing_point"> @@ -465,12 +465,12 @@ Media: <text name="Limit access to this parcel to:"> Accesso a questo terreno </text> - <check_box label="Consenti l'accesso pubblico [MATURITY]" name="public_access"/> + <check_box label="Consenti l'accesso pubblico (se si rimuove la selezione vengono create linee di espulsione)" name="public_access"/> <text name="Only Allow"> - Consenti l'accesso soltanto ai residenti verificati tramite: + Consenti l'accesso solo ai Residenti che: </text> - <check_box label="Informazioni di pagamento in archivio [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Espelli i residenti non identificati."/> - <check_box label="Verifica dell'età [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Espelli i residenti che non hanno la loro età verificata. Vedi [SUPPORT_SITE] per maggiori informazioni."/> + <check_box label="Hanno informazioni di pagamento in archivio [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Per poter visitare questo lotto i Residenti devono aver fornito informazioni di pagamento a Linden Lab. Vedi [SUPPORT_SITE] per maggiori informazioni."/> + <check_box label="Hanno verificato l'età [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Per poter visitare questo lotto i Residenti devono aver verificato la propria età . Vedi [SUPPORT_SITE] per maggiori informazioni."/> <check_box label="Permetti accesso al gruppo: [GROUP]" name="GroupCheck" tool_tip="Imposta il gruppo nel pannello generale."/> <check_box label="Vendi pass a:" name="PassCheck" tool_tip="Permetti in questo terreno l'accesso temporaneo"/> <combo_box name="pass_combo"> diff --git a/indra/newview/skins/default/xui/it/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/it/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..a2bce00141 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_animation_anim_preview.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Anim Preview" title="ANIMATION.ANIM"> + <text name="name_label"> + Nome: + </text> + <text name="description_label"> + Descrizione: + </text> + <button label="Carica ([AMOUNT] L$)" name="ok_btn"/> + <button label="Annulla" label_selected="Annulla" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_animation_bvh_preview.xml b/indra/newview/skins/default/xui/it/floater_animation_bvh_preview.xml new file mode 100644 index 0000000000..a4319f2e77 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_animation_bvh_preview.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Animation Preview"> + <floater.string name="failed_to_initialize"> + Movimento non inizializzato + </floater.string> + <floater.string name="anim_too_long"> + La lunghezza del file di animazione è di [LENGTH] secondi. + +La lunghezza massima dell'animazione è [MAX_LENGTH] secondi. + </floater.string> + <floater.string name="failed_file_read"> + Impossibile leggere il file di animazione. + +[STATUS] + </floater.string> + <floater.string name="E_ST_OK"> + Ok + </floater.string> + <floater.string name="E_ST_EOF"> + Fine prematura del file. + </floater.string> + <floater.string name="E_ST_NO_CONSTRAINT"> + Impossibile leggere la definizione del vincolo. + </floater.string> + <floater.string name="E_ST_NO_FILE"> + Impossibile aprire il file BVH. + </floater.string> + <floater.string name="E_ST_NO_HIER"> + Intestazione HIERARCHY non valida. + </floater.string> + <floater.string name="E_ST_NO_JOINT"> + Impossibile trovare la ROOT o JOINT. + </floater.string> + <floater.string name="E_ST_NO_NAME"> + Impossibile trovare il nome JOINT. + </floater.string> + <floater.string name="E_ST_NO_OFFSET"> + Impossibile trovare OFFSET. + </floater.string> + <floater.string name="E_ST_NO_CHANNELS"> + Impossibile trovare CHANNELS. + </floater.string> + <floater.string name="E_ST_NO_ROTATION"> + Impossibile ottenere un ordine di rotazione. + </floater.string> + <floater.string name="E_ST_NO_AXIS"> + Rotazione dell'asse non disponibile. + </floater.string> + <floater.string name="E_ST_NO_MOTION"> + Impossibile trovare MOTION. + </floater.string> + <floater.string name="E_ST_NO_FRAMES"> + Impossibile ottenere il numero dei frame. + </floater.string> + <floater.string name="E_ST_NO_FRAME_TIME"> + Impossibile ottenere il tempo del frame. + </floater.string> + <floater.string name="E_ST_NO_POS"> + Impossibile ottenere i valori della posizione. + </floater.string> + <floater.string name="E_ST_NO_ROT"> + Impossibile ottenere i valori di rotazione. + </floater.string> + <floater.string name="E_ST_NO_XLT_FILE"> + Impossibile aprire il file di traduzione. + </floater.string> + <floater.string name="E_ST_NO_XLT_HEADER"> + Impossibile leggere l'intestazione della traduzione. + </floater.string> + <floater.string name="E_ST_NO_XLT_NAME"> + Impossibile leggere i nomi della traduzione. + </floater.string> + <floater.string name="E_ST_NO_XLT_IGNORE"> + Impossibile leggere la traduzione, ignora il valore. + </floater.string> + <floater.string name="E_ST_NO_XLT_RELATIVE"> + Impossibile leggere la traduzione del valore relativo. + </floater.string> + <floater.string name="E_ST_NO_XLT_OUTNAME"> + Valore non trovato. + </floater.string> + <floater.string name="E_ST_NO_XLT_MATRIX"> + Impossibile leggere la matrice di traduzione. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGECHILD"> + Impossibile trovare il nome mergechild. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGEPARENT"> + Impossibile ottenere il nome mergeparent. + </floater.string> + <floater.string name="E_ST_NO_XLT_PRIORITY"> + Impossibile ottenere il valore di priorità . + </floater.string> + <floater.string name="E_ST_NO_XLT_LOOP"> + Impossibile ottenere il valore di ripetizione. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEIN"> + Impossibile ottenere i valori easeIn. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEOUT"> + Cannot get ease Out values. + </floater.string> + <floater.string name="E_ST_NO_XLT_HAND"> + Impossibile ottenere il valore morph della mano. + </floater.string> + <floater.string name="E_ST_NO_XLT_EMOTE"> + Impossibile leggere il nome emote. + </floater.string> + <floater.string name="E_ST_BAD_ROOT"> + Nome non corretto del root joint, usa "hip". + </floater.string> + <text name="name_label"> + Nome: + </text> + <text name="description_label"> + Descrizione: + </text> + <spinner label="Priorità " name="priority" tool_tip="Definisce quali altre animazioni possono essere sostituite da questa animazione"/> + <check_box label="Ripetizione" name="loop_check" tool_tip="Riproduce questa animazione in ripetizione"/> + <spinner label="Dentro(%)" name="loop_in_point" tool_tip="Imposta il punto sul quale ritorna l'animazione"/> + <spinner label="Fuori(%)" name="loop_out_point" tool_tip="Imposta il punto sul quale termina l'animazione"/> + <text name="hand_label"> + Posa delle mani + </text> + <combo_box name="hand_pose_combo" tool_tip="Definisce ciò che fanno le mani durante l'animazione"> + <combo_box.item label="Estese" name="Spread"/> + <combo_box.item label="Rilassate" name="Relaxed"/> + <combo_box.item label="Indicano entrambe" name="PointBoth"/> + <combo_box.item label="Pugno" name="Fist"/> + <combo_box.item label="Sinistra rilassata" name="RelaxedLeft"/> + <combo_box.item label="Indica sinistra" name="PointLeft"/> + <combo_box.item label="Pugno con la sinistra" name="FistLeft"/> + <combo_box.item label="Destra rilassata" name="RelaxedRight"/> + <combo_box.item label="Indica destra" name="PointRight"/> + <combo_box.item label="Pugno destro" name="FistRight"/> + <combo_box.item label="Saluta a destra" name="SaluteRight"/> + <combo_box.item label="Battitura" name="Typing"/> + <combo_box.item label="Pace a destra" name="PeaceRight"/> + </combo_box> + <text name="emote_label"> + Espressione + </text> + <combo_box name="emote_combo" tool_tip="Definisce ciò che fa il viso durante l'animazione"> + <item label="(Nulla)" name="[None]" value=""/> + <item label="Aaaaah" name="Aaaaah" value="Aaaaah"/> + <item label="Spavento" name="Afraid" value="Spavento"/> + <item label="Arrabbiato" name="Angry" value="Arrabbiato"/> + <item label="Grande sorriso" name="BigSmile" value="Grande sorriso"/> + <item label="Annoiato" name="Bored" value="Annoiato"/> + <item label="Pianto" name="Cry" value="Pianto"/> + <item label="Disdegno" name="Disdain" value="Disdegno"/> + <item label="Imbarazzato" name="Embarrassed" value="Imbarazzato"/> + <item label="Accigliato" name="Frown" value="Accigliato"/> + <item label="Bacio" name="Kiss" value="Bacio"/> + <item label="Risata" name="Laugh" value="Risata"/> + <item label="Linguaccia" name="Plllppt" value="Linguaccia"/> + <item label="Repulsione" name="Repulsed" value="Repulsione"/> + <item label="Triste" name="Sad" value="Triste"/> + <item label="Scrollata di spalle" name="Shrug" value="Scrollata di spalle"/> + <item label="Sorriso" name="Smile" value="Sorriso"/> + <item label="Stupore" name="Surprise" value="Stupore"/> + <item label="Occhiolino" name="Wink" value="Occhiolino"/> + <item label="Preoccupato" name="Worry" value="Preoccupato"/> + </combo_box> + <text name="preview_label"> + Anteprima mentre + </text> + <combo_box name="preview_base_anim" tool_tip="Prova il comportamento dell'animazione mentre l'avatar esegue attività comuni."> + <item label="In piedi" name="Standing" value="In piedi"/> + <item label="Camminare" name="Walking" value="Camminare"/> + <item label="Seduto" name="Sitting" value="Seduto"/> + <item label="Volare" name="Flying" value="Volare"/> + </combo_box> + <spinner label="Transizione in ingresso (sec)" name="ease_in_time" tool_tip="Durata (in secondi) della fusione in entrata delle animazioni"/> + <spinner label="Transizione in uscita (sec)" name="ease_out_time" tool_tip="Durata (in secondi) della fusione in uscita delle animazioni"/> + <button name="play_btn" tool_tip="Riproduci la tua animazione"/> + <button name="pause_btn" tool_tip="Metti in pausa la tua animazione"/> + <button name="stop_btn" tool_tip="Interrompi la riproduzione dell'animazione"/> + <text name="bad_animation_text"> + Impossibile leggere il file di animazione. + +Consigliamo file BVH esportati da Poser 4. + </text> + <button label="Carica ([AMOUNT] L$)" name="ok_btn"/> + <button label="Annulla" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/it/floater_merchant_outbox.xml new file mode 100644 index 0000000000..02f257d466 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_merchant_outbox.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_merchant_outbox" title="CASELLA IN USCITA DEL RIVENDITORE"> + <string name="OutboxFolderCount1"> + 1 cartella + </string> + <string name="OutboxFolderCountN"> + [NUM] cartelle + </string> + <string name="OutboxImporting"> + Invio cartelle... + </string> + <string name="OutboxInitializing"> + Inizializzazione... + </string> + <panel label=""> + <panel> + <panel name="outbox_inventory_placeholder_panel"> + <text name="outbox_inventory_placeholder_title"> + Caricamento... + </text> + </panel> + </panel> + <panel> + <button label="Invia a Marketplace" name="outbox_import_btn" tool_tip="Push su negozio Marketplace"/> + </panel> + </panel> +</floater> 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 7c1b13c18f..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="header_panel"> - <text name="header_text"> - Seleziona file modello - </text> - </panel> - <panel name="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="header_panel"> - <text name="header_text"> - Ottimizza modello - </text> - </panel> - <text name="description"> - Abbiamo ottimizzato il modello per migliorare le prestazioni. Se necessario, può essere regolato ulteriormente. - </text> - <panel name="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="header_panel"> - <text name="header_text"> - Modifica fisica - </text> - </panel> - <text name="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="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="header_panel"> - <text name="header_text"> - Rivedi - </text> - </panel> - <panel name="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="header_panel"> - <text name="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_preview_animation.xml b/indra/newview/skins/default/xui/it/floater_preview_animation.xml index 73082c9526..ed609c70fa 100644 --- a/indra/newview/skins/default/xui/it/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/it/floater_preview_animation.xml @@ -6,6 +6,6 @@ <text name="desc txt"> Descrizione: </text> - <button label="Riproduci in Second Life" label_selected="Ferma" left="20" name="Anim play btn" tool_tip="Riproduci questa animazione così che gli altri possano vederla" width="131"/> - <button label="Esegui localmente" label_selected="Ferma" left="162" name="Anim audition btn" tool_tip="Riproduci questa animazione così che solo tu possa vederla" width="125"/> + <button label="Riproduci in Second Life" label_selected="Ferma" name="Inworld" tool_tip="Riproduci questa animazione così che gli altri possano vederla"/> + <button label="Riproduci localmente" label_selected="Ferma" name="Locally" tool_tip="Riproduci questa animazione così che solo tu possa vederla"/> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/it/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..b479d5f6d6 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_test_layout_stacks.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="LAYOUTSTACK TESTS"/> diff --git a/indra/newview/skins/default/xui/it/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/it/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..23da6f7588 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_test_text_vertical_aligment.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="FINESTRA DI TEST"/> diff --git a/indra/newview/skins/default/xui/it/floater_tools.xml b/indra/newview/skins/default/xui/it/floater_tools.xml index 0d981e2424..c963ac72e6 100644 --- a/indra/newview/skins/default/xui/it/floater_tools.xml +++ b/indra/newview/skins/default/xui/it/floater_tools.xml @@ -1,5 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="toolbox floater" short_title="STRUMENTI PER COSTRUZIONE"> + <floater.string name="grid_screen_text"> + Schermo + </floater.string> + <floater.string name="grid_local_text"> + Locale + </floater.string> + <floater.string name="grid_world_text"> + Mondo + </floater.string> + <floater.string name="grid_reference_text"> + Riferimento + </floater.string> + <floater.string name="grid_attachment_text"> + Allegato + </floater.string> <floater.string name="status_rotate"> Sposta le fasce colorate per ruotare l'oggetto </floater.string> @@ -63,7 +78,12 @@ </text> <check_box initial_value="true" label="Ridimensiona le texture" name="checkbox stretch textures"/> <check_box initial_value="true" label="Scatto" name="checkbox snap to grid"/> - <button label="Opzioni..." label_selected="Opzioni..." name="Options..." tool_tip="Vedi più opzioni della griglia"/> + <combo_box name="combobox grid mode" tool_tip="Scegli il tipo di righello per posizionare l'oggetto"> + <combo_box.item label="Mondo" name="World"/> + <combo_box.item label="Locale" name="Local"/> + <combo_box.item label="Riferimento" name="Reference"/> + </combo_box> + <button label="" label_selected="Opzioni..." name="Options..." tool_tip="Vedi più opzioni della griglia"/> <button label="" label_selected="" name="ToolCube" tool_tip="Cubo"/> <button label="" label_selected="" name="ToolPrism" tool_tip="Prisma"/> <button label="" label_selected="" name="ToolPyramid" tool_tip="Piramide"/> diff --git a/indra/newview/skins/default/xui/it/floater_voice_effect.xml b/indra/newview/skins/default/xui/it/floater_voice_effect.xml index a0e49525ea..c83b11f698 100644 --- a/indra/newview/skins/default/xui/it/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/it/floater_voice_effect.xml @@ -42,13 +42,16 @@ <string name="effect_Demon"> Demonio </string> + <string name="effect_Female Elf"> + Elfo donna + </string> <string name="effect_Flirty"> Civettuolo </string> <string name="effect_Foxy"> Scaltro </string> - <string name="effect_Halloween_2010_Bonus"> + <string name="effect_Halloween 2010 Bonus"> Halloween_2010_Bonus </string> <string name="effect_Helium"> @@ -57,9 +60,18 @@ <string name="effect_Husky"> Fusto </string> + <string name="effect_Husky Whisper"> + Sospiro rauco + </string> <string name="effect_Intercom"> Interfono </string> + <string name="effect_Julia"> + Julia + </string> + <string name="effect_Lo Lilt"> + Inflessione bassa + </string> <string name="effect_Macho"> Macho </string> @@ -69,6 +81,9 @@ <string name="effect_Mini"> Mini </string> + <string name="effect_Model"> + Modella + </string> <string name="effect_Nano"> Nano </string> @@ -90,6 +105,9 @@ <string name="effect_Roxanne"> Rosanna </string> + <string name="effect_Rumble"> + Rombo + </string> <string name="effect_Sabrina"> Sabrina </string> @@ -102,6 +120,9 @@ <string name="effect_Shorty"> Bassotto </string> + <string name="effect_Smaller"> + Più piccolo + </string> <string name="effect_Sneaky"> Vile </string> diff --git a/indra/newview/skins/default/xui/it/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/it/menu_inspect_object_gear.xml index ede4a507c0..4740c9bf67 100644 --- a/indra/newview/skins/default/xui/it/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/it/menu_inspect_object_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<menu name="Gear Menu"> +<toggleable_menu name="Gear Menu"> <menu_item_call label="Tocca" name="touch"/> <menu_item_call label="Siediti" name="sit"/> <menu_item_call label="Paga" name="pay"/> @@ -12,7 +12,8 @@ <menu_item_call label="Aggiungi" name="add"/> <menu_item_call label="Segnala" name="report"/> <menu_item_call label="Blocca" name="block"/> + <menu_item_call label="Sblocca" name="unblock"/> <menu_item_call label="Zoom avanti" name="zoom_in"/> <menu_item_call label="Rimuovi" name="remove"/> <menu_item_call label="Maggiori informazioni" name="more_info"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/it/menu_inventory.xml b/indra/newview/skins/default/xui/it/menu_inventory.xml index 57aa4dc97d..4bf6be82fd 100644 --- a/indra/newview/skins/default/xui/it/menu_inventory.xml +++ b/indra/newview/skins/default/xui/it/menu_inventory.xml @@ -59,6 +59,7 @@ <menu_item_call label="Proprietà " name="Properties"/> <menu_item_call label="Rinomina" name="Rename"/> <menu_item_call label="Copia UUID dell'oggetto" name="Copy Asset UUID"/> + <menu_item_call label="Taglia" name="Cut"/> <menu_item_call label="Copia" name="Copy"/> <menu_item_call label="Incolla" name="Paste"/> <menu_item_call label="Incolla come link" name="Paste As Link"/> @@ -84,6 +85,6 @@ <menu_item_call label="Aggiungi" name="Wearable Add"/> <menu_item_call label="Togli" name="Take Off"/> <menu_item_call label="Copia nella casella venditore in uscita" name="Merchant Copy"/> - <menu_item_call label="Passa alla casella venditore in uscita" name="Merchant Move"/> + <menu_item_call label="Invia a Marketplace" name="Marketplace Send"/> <menu_item_call label="--nessuna opzione--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/it/menu_login.xml b/indra/newview/skins/default/xui/it/menu_login.xml index 834db974da..7b060e6565 100644 --- a/indra/newview/skins/default/xui/it/menu_login.xml +++ b/indra/newview/skins/default/xui/it/menu_login.xml @@ -16,8 +16,8 @@ <menu_item_call label="Imposta dimensioni della finestra..." name="Set Window Size..."/> <menu_item_call label="Mostra i Termini del servizio (TOS)" name="TOS"/> <menu_item_call label="Mostra messaggio critico" name="Critical"/> - <menu_item_call label="Test browser multimedia" name="Web Browser Test"/> <menu_item_call label="Test debug finestra contenuti Web" name="Web Content Floater Debug Test"/> + <menu label="Imposta livello di registrazione" name="Set Logging Level"/> <menu_item_check label="Mostra selettore griglia" name="Show Grid Picker"/> <menu_item_call label="Mostra Console notifiche" name="Show Notifications Console"/> </menu> diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml index 5140d2b1ec..99b7e3c4e6 100644 --- a/indra/newview/skins/default/xui/it/menu_viewer.xml +++ b/indra/newview/skins/default/xui/it/menu_viewer.xml @@ -14,14 +14,14 @@ <menu_item_check label="Vola" name="Fly"/> <menu_item_check label="Corri sempre" name="Always Run"/> <menu_item_call label="Ferma animazione" name="Stop Animating My Avatar"/> + <menu_item_call label="Cammina / corri / vola..." name="Walk / run / fly"/> </menu> <menu label="Stato" name="Status"> <menu_item_call label="Assente" name="Set Away"/> <menu_item_call label="Non disponibile" name="Set Busy"/> </menu> - <menu_item_call label="Richiedi diritti Admin" name="Request Admin Options"/> - <menu_item_call label="Lascia stato Admin" name="Leave Admin Options"/> - <menu_item_call label="Compra L$" name="Buy and Sell L$"/> + <menu_item_call label="Acquista L$..." name="Buy and Sell L$"/> + <menu_item_call label="Casella venditore in uscita..." name="MerchantOutbox"/> <menu_item_call label="Dashboard dell'account..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=it"/> </menu_item_call> @@ -63,7 +63,7 @@ <menu_item_check label="Proprietà del lotto" name="Parcel Properties"/> <menu_item_check label="Menu Avanzato" name="Show Advanced Menu"/> </menu> - <menu label="Sole" name="Environment Settings"> + <menu label="Sole" name="Sun"> <menu_item_call label="Alba" name="Sunrise"/> <menu_item_call label="Mezzogiorno" name="Noon"/> <menu_item_call label="Tramonto" name="Sunset"/> @@ -178,22 +178,22 @@ <menu_item_check label="Mostra mirino visuale soggettiva" name="ShowCrosshairs"/> </menu> <menu label="Modalità di rendering" name="Rendering Types"> - <menu_item_check label="Semplice" name="Simple"/> - <menu_item_check label="Alpha (Trasparenza)" name="Alpha"/> - <menu_item_check label="Albero" name="Tree"/> - <menu_item_check label="Avatar" name="Character"/> - <menu_item_check label="Superficie chiusa" name="Surface Patch"/> - <menu_item_check label="Cielo" name="Sky"/> - <menu_item_check label="Acqua" name="Water"/> - <menu_item_check label="Suolo" name="Ground"/> - <menu_item_check label="Volume" name="Volume"/> - <menu_item_check label="Erba" name="Grass"/> - <menu_item_check label="Nuvole" name="Clouds"/> - <menu_item_check label="Particelle" name="Particles"/> - <menu_item_check label="Urti" name="Bump"/> + <menu_item_check label="Semplice" name="Rendering Type Simple"/> + <menu_item_check label="Alpha (Trasparenza)" name="Rendering Type Alpha"/> + <menu_item_check label="Albero" name="Rendering Type Tree"/> + <menu_item_check label="Avatar" name="Rendering Type Character"/> + <menu_item_check label="Toppa superficie" name="Rendering Type Surface Patch"/> + <menu_item_check label="Cielo" name="Rendering Type Sky"/> + <menu_item_check label="Acqua" name="Rendering Type Water"/> + <menu_item_check label="Suolo" name="Rendering Type Ground"/> + <menu_item_check label="Volume" name="Rendering Type Volume"/> + <menu_item_check label="Erba" name="Rendering Type Grass"/> + <menu_item_check label="Nuvole" name="Rendering Type Clouds"/> + <menu_item_check label="Particelle" name="Rendering Type Particles"/> + <menu_item_check label="Urto" name="Rendering Type Bump"/> </menu> <menu label="Caratteristiche di rendering" name="Rendering Features"> - <menu_item_check label="Interfaccia utente" name="UI"/> + <menu_item_check label="Interfaccia utente" name="ToggleUI"/> <menu_item_check label="Selezionati" name="Selected"/> <menu_item_check label="Evidenziato" name="Highlighted"/> <menu_item_check label="Texture dinamiche" name="Dynamic Textures"/> @@ -206,8 +206,6 @@ <menu_item_check label="Fluidità mouse" name="Mouse Smoothing"/> <menu_item_call label="Rilascia tasti" name="Release Keys"/> <menu label="Scorciatoie" name="Shortcuts"> - <menu_item_call label="Immagine ([COST]L$)..." name="Upload Image"/> - <menu_item_check label="Cerca" name="Search"/> <menu_item_check label="Mostra menu Avanzato - tasti di scelta rapida esistenti" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Chiudi finestra" name="Close Window"/> <menu_item_call label="Chiudi tutte le finestre" name="Close All Windows"/> @@ -216,13 +214,6 @@ <menu_item_check label="Joystick Flycam" name="Joystick Flycam"/> <menu_item_call label="Reimposta vista" name="Reset View"/> <menu_item_call label="Guarda l'ultima conversazione" name="Look at Last Chatter"/> - <menu label="Seleziona strumento di costruzione" name="Select Tool"> - <menu_item_call label="Strumento Ingrandisci" name="Focus"/> - <menu_item_call label="Strumento Movimento" name="Move"/> - <menu_item_call label="Strumento Modifica" name="Edit"/> - <menu_item_call label="Strumento Crea" name="Create"/> - <menu_item_call label="Strumento Terreno" name="Land"/> - </menu> <menu_item_call label="Zoom avanti" name="Zoom In"/> <menu_item_call label="Zoom predefinito" name="Zoom Default"/> <menu_item_call label="Zoom indietro" name="Zoom Out"/> @@ -278,6 +269,7 @@ <menu_item_check label="Crea coda" name="Build Queue"/> <menu_item_check label="Vettori vento" name="Wind Vectors"/> <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> <menu label="Rendering" name="Rendering"> @@ -300,9 +292,8 @@ <menu_item_call label="Lascia un pacchetto" name="Drop a Packet"/> </menu> <menu_item_call label="Urti, spinte e contatti" name="Bumps, Pushes &amp; Hits"/> - <menu label="Mondo" name="World"> - <menu_item_check label="Esclusione al sole della regione" name="Sim Sun Override"/> - <menu_item_check label="Effetto marcatore lampeggiante" name="Cheesy Beacon"/> + <menu label="Mondo" name="DevelopWorld"> + <menu_item_check label="Esclusione al sole della simulazione" name="Sim Sun Override"/> <menu_item_check label="Clima fisso" name="Fixed Weather"/> <menu_item_call label="Dump della cache oggetti regione" name="Dump Region Object Cache"/> </menu> @@ -324,11 +315,11 @@ </menu> <menu label="Avatar" name="Character"> <menu label="Grab Baked Texture" name="Grab Baked Texture"> - <menu_item_call label="Iride" name="Iris"/> - <menu_item_call label="Testa" name="Head"/> - <menu_item_call label="Parte superiore del corpo" name="Upper Body"/> - <menu_item_call label="Parte inferiore del corpo" name="Lower Body"/> - <menu_item_call label="Gonna" name="Skirt"/> + <menu_item_call label="Iride" name="Grab Iris"/> + <menu_item_call label="Testa" name="Grab Head"/> + <menu_item_call label="Parte superiore del corpo" name="Grab Upper Body"/> + <menu_item_call label="Parte inferiore del corpo" name="Grab Lower Body"/> + <menu_item_call label="Gonna" name="Grab Skirt"/> </menu> <menu label="Test personaggio" name="Character Tests"> <menu_item_call label="Alterna la geometria dei personaggi" name="Toggle Character Geometry"/> @@ -344,18 +335,27 @@ </menu> <menu_item_check label="Texture HTTP" name="HTTP Textures"/> <menu_item_check label="Inventario HTTP" name="HTTP Inventory"/> + <menu_item_call label="Attiva Visual Leak Detector" name="Enable Visual Leak Detector"/> <menu_item_check label="Finestra Console al prossimo lancio" name="Console Window"/> + <menu label="Imposta livello di registrazione" name="Set Logging Level"> + <menu_item_check label="Debug" name="Debug"/> + <menu_item_check label="Informazioni" name="Info"/> + <menu_item_check label="Attenzione" name="Warning"/> + <menu_item_check label="Errore" name="Error"/> + <menu_item_check label="Nessuno" name="None"/> + </menu> <menu_item_call label="Richiedi diritti Admin" name="Request Admin Options"/> <menu_item_call label="Lascia stato Admin" name="Leave Admin Options"/> <menu_item_check label="Mostra menu Admin" name="View Admin Options"/> </menu> <menu label="Admin" name="Admin"> - <menu label="Object"> - <menu_item_call label="Prendi copia" name="Take Copy"/> + <menu label="Oggetto" name="AdminObject"> + <menu_item_call label="Prendi copia" name="Admin Take Copy"/> <menu_item_call label="Rendimi proprietario" name="Force Owner To Me"/> <menu_item_call label="Forza permesso proprietario" name="Force Owner Permissive"/> <menu_item_call label="Elimina" name="Delete"/> <menu_item_call label="Blocca" name="Lock"/> + <menu_item_call label="Ottieni ID asset" name="Get Assets IDs"/> </menu> <menu label="Lotto" name="Parcel"> <menu_item_call label="Rendimi proprietario" name="Owner To Me"/> @@ -372,5 +372,16 @@ <menu label="Take Off Clothing" name="Take Off Clothing"> <menu_item_call label="Fisica" name="Physics"/> </menu> + <menu label="Guida" name="DeprecatedHelp"> + <menu_item_call label="Blog ufficiale Linden" name="Official Linden Blog"/> + <menu_item_call label="Portale script" name="Scripting Portal"/> + <menu label="Segnalazione bug" name="Bug Reporting"> + <menu_item_call label="Monitoraggio problemi pubblici" name="Public Issue Tracker"/> + <menu_item_call label="Guida Monitoraggio problemi pubblici" name="Publc Issue Tracker Help"/> + <menu_item_call label="Guida alla segnalazione di bug" name="Bug Reporing 101"/> + <menu_item_call label="Problemi sicurezza" name="Security Issues"/> + <menu_item_call label="Wiki domande e risposte" name="QA Wiki"/> + </menu> + </menu> </menu> </menu_bar> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index fcc515186d..0e6fee60d1 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -86,17 +86,38 @@ Accertati che la tua connessione Internet stia funzionando correttamente. <usetemplate canceltext="Annulla" name="yesnocancelbuttons" notext="Non salvare" yestext="Salva"/> </notification> <notification name="ConfirmNoCopyToOutbox"> - Non hai l'autorizzazione necessaria per copiare questo oggetto nella casella in uscita di Marketplace. Sei sicuro di volere spostare gli oggetti seguenti? - [ITEM_NAME] - <usetemplate name="okcancelbuttons" notext="No" yestext="Sì"/> + Non hai l'autorizzazione necessaria per copiare almeno uno di questi elementi nella casella in uscita del rivenditore. Puoi spostarli o lasciarli indietro. + <usetemplate name="okcancelbuttons" notext="Non spostare gli oggetti" yestext="Sposta oggetti"/> </notification> - <notification name="OutboxUploadComplete"> - Caricamento di Marketplace completato. - <usetemplate name="okbutton" yestext="Ottimo!"/> + <notification name="OutboxFolderCreated"> + Una nuova cartella è stata creata per ciascun elemento trasferito nel livello superiore della casella in uscita del rivenditore. + <usetemplate ignoretext="Una nuova cartella è stata creata nella casella in uscita del rivenditore" name="okignore" yestext="OK"/> </notification> - <notification name="OutboxUploadHadErrors"> - Caricamento di Marketplace completato senza errori. Correggi i problemi nella casella in uscita e riprova. Grazie. - <usetemplate name="okbutton" yestext="Riprova"/> + <notification name="OutboxImportComplete"> + Successo + +Tutte le cartelle sono state inviate a Marketplace correttamente. + <usetemplate ignoretext="Tutte le cartelle inviate a Marketplace" name="okignore" yestext="OK"/> + </notification> + <notification name="OutboxImportHadErrors"> + Alcune cartelle non sono state trasferite + +Si sono verificati degli errori durante l'invio di alcune cartelle a Marketplace. Tali cartelle sono ancora nella casella in uscita del rivenditore. + +Per ulteriori informazioni consulta il [[MARKETPLACE_IMPORTS_URL] registro errori]. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxImportFailed"> + Trasferimento non riuscito + +Nessuna cartella è stata inviata a Marketplace, a causa di un errore di sistema o di rete. Riprova più tardi. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxInitFailed"> + Inizializzazione Marketplace non riuscita + +L'inizializzazione con il Marketplace non ha avuto successo a causa di un errore di sistema o di rete. Riprova più tardi. + <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="CompileQueueSaveText"> C'è stato un problema importando il testo di uno script per la seguente ragione: [REASON]. Riprova più tardi. @@ -647,7 +668,7 @@ Attese [VALIDS] Impossibile creare il file in uscita: [FILE] </notification> <notification name="DoNotSupportBulkAnimationUpload"> - [APP_NAME] non supporta ancora il caricamento in blocco di file di animazione. + [APP_NAME] non supporta ancora il caricamento in blocco di file di animazione in formato BVH. </notification> <notification name="CannotUploadReason"> Impossibile importare il file [FILE] a causa del seguente motivo: [REASON] @@ -1437,8 +1458,8 @@ Per installare l'aggiornamento è necessario riavviare [APP_NAME]. <usetemplate ignoretext="Conferma prima di restituire gli oggetti ai relativi proprietari" name="okcancelignore" notext="Annulla" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Sei attualmente un membro del gruppo <nolink>[GROUP]</nolink>. -Vuoi lasciare il gruppo? + Attualmente sei un membro del gruppo <nolink>[GROUP]</nolink>. +Lasciare il gruppo? <usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/> </notification> <notification name="ConfirmKick"> @@ -2611,16 +2632,16 @@ Concedi questa richiesta? '<nolink>[TITLE]</nolink>' di [NAME] [MESSAGE] <form name="form"> - <button name="Mute" text="Blocca"/> - <button name="Ignore" text="Ignora"/> + <button name="Client_Side_Mute" text="Blocca"/> + <button name="Client_Side_Ignore" text="Ignora"/> </form> </notification> <notification name="ScriptDialogGroup"> '<nolink>[TITLE]</nolink>' di [GROUPNAME] [MESSAGE] <form name="form"> - <button name="Mute" text="Blocca"/> - <button name="Ignore" text="Ignora"/> + <button name="Client_Side_Mute" text="Blocca"/> + <button name="Client_Side_Ignore" text="Ignora"/> </form> </notification> <notification name="BuyLindenDollarSuccess"> @@ -2818,6 +2839,18 @@ Con i seguenti residenti? [RESIDENTS] <usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/> </notification> + <notification name="ShareFolderConfirmation"> + Si può condividere solo una cartella alla volta. + +Sei sicuro di volere condividere gli oggetti seguenti: + +<nolink>[ITEMS]</nolink> + +Con i seguenti residenti: + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="Annulla" yestext="Ok"/> + </notification> <notification name="ItemsShared"> Gli oggetti sono stati condivisi. </notification> diff --git a/indra/newview/skins/default/xui/it/panel_nearby_chat.xml b/indra/newview/skins/default/xui/it/panel_nearby_chat.xml index 1b529e2737..d46a15c735 100644 --- a/indra/newview/skins/default/xui/it/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/it/panel_nearby_chat.xml @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="nearby_chat"> - <check_box label="Traduci chat" name="translate_chat_checkbox"/> + <layout_stack name="stack"> + <layout_panel name="translate_chat_checkbox_lp"> + <check_box label="Traduci chat" name="translate_chat_checkbox"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/it/panel_region_estate.xml b/indra/newview/skins/default/xui/it/panel_region_estate.xml index 61e3f31024..da6b6b277f 100644 --- a/indra/newview/skins/default/xui/it/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/it/panel_region_estate.xml @@ -23,10 +23,10 @@ <check_box label="Permetti accesso pubblico" name="externally_visible_check"/> <button label="?" name="externally_visible_help"/> <text name="Only Allow"> - Limita l'accesso agli account verificati con: + Consenti l'accesso solo ai Residenti che: </text> - <check_box label="Informazioni di pagamento in archivio" name="limit_payment" tool_tip="Espelli i residenti non identificati"/> - <check_box label="Verifica età " name="limit_age_verified" tool_tip="Espelli i residenti che non hanno la loro età verificata. Vedi [SUPPORT_SITE] per maggiori informazioni."/> + <check_box label="Hanno memorizzato le informazioni per l'addebito" name="limit_payment" tool_tip="Per poter visitare questa proprietà immobiliare i Residenti devono aver fornito informazioni di pagamento a Linden Lab. Vedi [SUPPORT_SITE] per maggiori informazioni."/> + <check_box label="Hanno verificato l'età " name="limit_age_verified" tool_tip="Per poter visitare questa proprietà immobiliare i Residenti devono aver verificato la propria età . Vedi [SUPPORT_SITE] per maggiori informazioni."/> <check_box label="Permetti la chat voice" name="voice_chat_check"/> <button label="?" name="voice_chat_help"/> <check_box label="Permetti teleport diretto" name="allow_direct_teleport"/> diff --git a/indra/newview/skins/default/xui/it/panel_script_ed.xml b/indra/newview/skins/default/xui/it/panel_script_ed.xml index 950dfacf3a..d7ee8230b3 100644 --- a/indra/newview/skins/default/xui/it/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/it/panel_script_ed.xml @@ -22,6 +22,8 @@ <menu label="File" name="File"> <menu_item_call label="Salva" name="Save"/> <menu_item_call label="Annulla tutte le modifiche" name="Revert All Changes"/> + <menu_item_call label="Carica da file..." name="LoadFromFile"/> + <menu_item_call label="Salva su file..." name="SaveToFile"/> </menu> <menu label="Modifica" name="Edit"> <menu_item_call label="Annulla" name="Undo"/> diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml index 4abc90113f..0aaf89d8c8 100644 --- a/indra/newview/skins/default/xui/it/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml @@ -15,7 +15,7 @@ <panel.string name="buycurrencylabel"> L$ [AMT] </panel.string> - <panel name="balance_bg"> + <panel left="-405" name="balance_bg" width="195"> <text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ 20"/> <button label="Acquista L$" name="buyL" tool_tip="Clicca per acquistare più L$"/> <button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life" width="75"/> diff --git a/indra/newview/skins/default/xui/it/sidepanel_inventory.xml b/indra/newview/skins/default/xui/it/sidepanel_inventory.xml index 5d6c7681f9..5ac0961bd7 100644 --- a/indra/newview/skins/default/xui/it/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/it/sidepanel_inventory.xml @@ -2,47 +2,24 @@ <panel label="Cose" name="objects panel"> <panel label="" name="sidepanel__inventory_panel"> <layout_stack name="inventory_layout_stack"> - <layout_panel name="inbox_outbox_layout_panel"> - <layout_stack name="inbox_outbox_layout_stack"> - <layout_panel name="inbox_layout_panel"> - <panel label="" name="marketplace_inbox"> - <string name="InboxLabelWithArg"> - Oggetti ricevuti ([NUM]) - </string> - <string name="InboxLabelNoArg"> - Oggetti ricevuti - </string> - <button label="Oggetti ricevuti" name="inbox_btn"/> - <text name="inbox_fresh_new_count"> - [NUM] nuovi - </text> - <panel tool_tip="Drag and drop items to your inventory to manage and use them"> - <text name="inbox_inventory_placeholder"> - Gli acquisti dal mercato verranno consegnati qui. - </text> - </panel> - </panel> - </layout_panel> - <layout_panel name="outbox_layout_panel"> - <panel label="" name="marketplace_outbox"> - <string name="OutboxLabelWithArg"> - Casella venditore in uscita ([NUM]) - </string> - <string name="OutboxLabelNoArg"> - Casella venditore in uscita - </string> - <button label="Casella venditore in uscita" name="outbox_btn"/> - <button label="" name="outbox_sync_btn" tool_tip="Push su negozio Marketplace"/> - <panel> - <panel name="outbox_inventory_placeholder_panel"> - <text name="outbox_inventory_placeholder_title"> - Caricamento in corso... - </text> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> + <layout_panel name="inbox_layout_panel"> + <panel label="" name="marketplace_inbox"> + <string name="InboxLabelWithArg"> + Oggetti ricevuti ([NUM]) + </string> + <string name="InboxLabelNoArg"> + Oggetti ricevuti + </string> + <button label="Oggetti ricevuti" name="inbox_btn"/> + <text name="inbox_fresh_new_count"> + [NUM] nuovi + </text> + <panel name="inbox_inventory_placeholder_panel" tool_tip="Trascina gli elementi nell'inventario per usarli"> + <text name="inbox_inventory_placeholder"> + Gli acquisti dal mercato verranno consegnati qui. + </text> + </panel> + </panel> </layout_panel> </layout_stack> <panel name="button_panel"> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index c81dd0f55d..8529fadd7d 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -178,8 +178,8 @@ Visita www.secondlife.com/status per aggiornamenti. </string> <string name="LoginFailedPremiumOnly"> L'accesso a Second Life è temporaneamente limitato per garantire che chi è nel mondo virtuale abbia la migliore esperienza possibile. - -Le persona con account gratuiti non potrenno accedere a Second Life durante questo periodo, per lasciare spazio alle persone che hanno pagato per Second Life. + +Le persone con account gratuiti non potranno accedere a Second Life durante questo periodo, per lasciare spazio alle persone che hanno pagato per Second Life. </string> <string name="LoginFailedComputerProhibited"> Non si può accedere a Second Life da questo computer. @@ -336,17 +336,35 @@ Prova ad accedere nuovamente tra un minuto. Solo un singolo oggetto può essere creato qui </string> <string name="TooltipPrice" value="L$ [AMOUNT]:"/> + <string name="TooltipOutboxDragToWorld"> + Non puoi rezzare elementi nella tua casella in uscita del rivenditore + </string> <string name="TooltipOutboxNoTransfer"> - Almeno un oggetto non può essere venduto o trasferito a un altro utente. + Almeno uno di questi oggetti non può essere venduto o trasferito. + </string> + <string name="TooltipOutboxNotInInventory"> + La tua casella in uscita del rivenditore può accettare solo elementi provenienti dal tuo inventario </string> <string name="TooltipOutboxWorn"> - Stai indossando almeno uno degli oggetti. Rimuovili dall'avatar e prova nuovamente a spostarli. + Non puoi mettere gli elementi che indossi nella casella in uscita del rivenditore + </string> + <string name="TooltipOutboxCallingCard"> + Non puoi inserire il tuo biglietto da visita nella tua casella in uscita del rivenditore </string> <string name="TooltipOutboxFolderLevels"> - Questa cartella contiene troppi livelli di cartelle nidificate. Riordina le cartelle interne in modo che non ci siano più di 4 livelli (cartella principale che contiene la cartella A, che contiene la cartella B, che contiene la cartella C). + La profondità delle caselle nidificate è maggiore di 3 + </string> + <string name="TooltipOutboxTooManyFolders"> + Il numero di sottocartelle nella cartella al livello più alto è maggiore di 20 </string> <string name="TooltipOutboxTooManyObjects"> - Questa cartella contiene più di 200 oggetti. Inserisci alcuni oggetti in scatole per ridurne il numero. + Il numero di elementi nella cartella al livello più alto è maggiore di 200 + </string> + <string name="TooltipDragOntoOwnChild"> + Non puoi spostare una cartella nella relativa cartella secondaria + </string> + <string name="TooltipDragOntoSelf"> + Non puoi spostare una cartella in se stessa </string> <string name="TooltipHttpUrl"> Clicca per visitare questa pagina web @@ -811,6 +829,9 @@ Prova ad accedere nuovamente tra un minuto. <string name="anim_yes_head"> Si </string> + <string name="multiple_textures"> + Multiple + </string> <string name="texture_loading"> Caricamento in corso... </string> @@ -967,6 +988,9 @@ Prova ad accedere nuovamente tra un minuto. <string name="choose_the_directory"> Scegli la cartella </string> + <string name="script_files"> + Script + </string> <string name="AvatarSetNotAway"> Imposta come non assente </string> @@ -1205,43 +1229,36 @@ Prova ad accedere nuovamente tra un minuto. Non hai una copia di questa texture nel tuo inventario </string> <string name="InventoryInboxNoItems"> - Quando acquisti o ricevi un oggetto, verrà visualizzato qui per permetterti di trascinarlo in una cartella dell'inventario o di cancellarlo se non desideri mantenerlo. + Gli acquissti dal mercato verranno mostrati qui. Potrai quindi trascinarli nel tuo inventario per usarli. </string> <string name="MarketplaceURL"> - http://marketplace.[DOMAIN_NAME]/learn_more + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/ </string> <string name="MarketplaceURL_CreateStore"> - http://marketplace.[DOMAIN_NAME]/create_store + http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 </string> - <string name="MarketplaceURL_LearnMore"> - http://marketplace.[DOMAIN_NAME]/learn_more - </string> - <string name="InventoryOutboxCreationErrorTitle"> - La casella in uscita del rivenditore non è configurata correttamente + <string name="MarketplaceURL_Dashboard"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard </string> - <string name="InventoryOutboxCreationErrorTooltip"> - Errore di configurazione della casella in uscita del rivenditore + <string name="MarketplaceURL_Imports"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports </string> - <string name="InventoryOutboxCreationError"> - Contatta l'Assistenza clienti per correggere il problema. + <string name="MarketplaceURL_LearnMore"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more </string> <string name="InventoryOutboxNotMerchantTitle"> - Chiunque può vendere oggetti nel Marketplace - </string> - <string name="InventoryOutboxNotMerchantTooltip"> - Diventa un rivenditore! + Chiunque può vendere oggetti nel Marketplace. </string> + <string name="InventoryOutboxNotMerchantTooltip"/> <string name="InventoryOutboxNotMerchant"> - [[MARKETPLACE_URL] Second Life Marketplace] offre in vendita più di un milione di prodotti virtuali, tutti creati da Residenti. Anche tu puoi vendere gli oggetti che crei, oltre ad alcuni degli oggetti che hai acquistato. È facile da usare e l'impostazione è gratuita. [[LEARN_MORE_URL] Leggi ulteriori informazioni] oppure [[CREATE_STORE_URL] crea un negozio] sul Marketplace per cominciare. + Per diventare un venditore, devi [[MARKETPLACE_CREATE_STORE_URL] creare un negozio nel Marketplace]. </string> <string name="InventoryOutboxNoItemsTitle"> - Un nuovo modo di inviare oggetti al Marketplace - </string> - <string name="InventoryOutboxNoItemsTooltip"> - Trascina gli oggetti qui per prepararli per la vendita nel Marketplace + La tua casella in uscita è vuota. </string> + <string name="InventoryOutboxNoItemsTooltip"/> <string name="InventoryOutboxNoItems"> - Trascina elementi o cartelle che desideri vendere in quest'area. Verrà visualizzata una copia dell'elemento, senza che venga modificato l'inventario, tranne nel caso in cui venga trascinato un oggetto per cui non è permessa la copia. Clicca sul pulsante Carica per caricare gli elementi su Marketplace. Dopo aver spostato gli elementi nell'inventario di Marketplace, non saranno più visibili in questa cartella. + Trascina le cartelle in questa area e clicca su "Invia a Marketplace" per metterle in vendita su [[MARKETPLACE_DASHBOARD_URL] Marketplace]. </string> <string name="Marketplace Error None"> Nessun errore @@ -1253,7 +1270,7 @@ Prova ad accedere nuovamente tra un minuto. Errore: questa cartella non include alcun contenuto. </string> <string name="Marketplace Error Unassociated Products"> - Errore: Oggetto non caricato perché il tuo account venditore ha troppi oggetti che non sono associati con dei prodotti. Per risolvere questo errore, esegui l'accesso al sito di Marketplace e riduci il numero di oggetti non associati. + Errore: Oggetto non caricato perché il tuo account venditore ha troppi oggetti che non sono associati con dei prodotti. Per risolvere questo errore, esegui l'accesso al sito di Marketplace e riduci il numero di oggetti non associati. </string> <string name="Marketplace Error Object Limit"> Errore: questo elemento contiene troppi oggetti. Per risolvere questo problema, inserisci più oggetti insieme in una scatola per ridurre a meno di 200 il numero totale di oggetti. @@ -3829,6 +3846,9 @@ Se il messaggio persiste, contatta [SUPPORT_SITE]. <string name="Saved_message"> (Salvato [LONG_TIMESTAMP]) </string> + <string name="IM_unblock_only_groups_friends"> + Per vedere questo messaggio, devi deselezionare 'Solo amici e gruppi possono chiamarmi o mandarmi IM' in Preferenze/Privacy. + </string> <string name="answered_call"> Risposto alla chiamata </string> @@ -4014,7 +4034,7 @@ Se il messaggio persiste, contatta [SUPPORT_SITE]. </string> <string name="uploading_abuse_report"> Caricamento in corso... - + Segnala abuso </string> <string name="New Shape"> @@ -4282,7 +4302,7 @@ Segnala abuso <string name="server_is_down"> Nonostante i nostri tentativi, si è verificato un errore imprevisto. - Consulta la pagina status.secondlifegrid.net per determinare se si sia verificato un problema noto con il servizio. + Consulta la pagina status.secondlifegrid.net per determinare se si sia verificato un problema noto con il servizio. Se il problema continua, ti consigliamo di controllare le tue impostazioni di rete e della firewall. </string> <string name="dateTimeWeekdaysNames"> @@ -4749,6 +4769,9 @@ Prova a racchiudere il percorso dell'editor in doppie virgolette. <string name="Command_Move_Label"> Cammina / corri / vola </string> + <string name="Command_Outbox_Label"> + Casella in uscita del rivenditore + </string> <string name="Command_People_Label"> Persone </string> @@ -4821,6 +4844,9 @@ Prova a racchiudere il percorso dell'editor in doppie virgolette. <string name="Command_Move_Tooltip"> Movimento avatar </string> + <string name="Command_Outbox_Tooltip"> + Trasferisci elementi al tuo mercato per la vendita + </string> <string name="Command_People_Tooltip"> Amici, gruppi e persone vicine </string> diff --git a/indra/newview/skins/default/xui/ja/floater_about_land.xml b/indra/newview/skins/default/xui/ja/floater_about_land.xml index 816a6ff203..7c87bad5a3 100644 --- a/indra/newview/skins/default/xui/ja/floater_about_land.xml +++ b/indra/newview/skins/default/xui/ja/floater_about_land.xml @@ -375,7 +375,7 @@ </text> <texture_picker label="" name="snapshot_ctrl" tool_tip="写真をクリックã—ã¦é¸æŠž"/> <text name="allow_label5"> - ã“ã®åŒºç”»ã«ã„ã‚‹ã‚¢ãƒã‚¿ãƒ¼ã«ä¼šã£ã¦ãƒãƒ£ãƒƒãƒˆã§ãã¾ã™ + ä»–ã®åŒºç”»ã«ã„ã‚‹ã‚¢ãƒã‚¿ãƒ¼ãŒã“ã®åŒºç”»ã«ã„ã‚‹ã‚¢ãƒã‚¿ãƒ¼ã«ä¼šã£ã¦ãƒãƒ£ãƒƒãƒˆã§ãã‚‹ </text> <check_box label="ã‚¢ãƒã‚¿ãƒ¼ã‚’表示" name="SeeAvatarsCheck" tool_tip="ä»–ã®åŒºç”»ã®ã‚¢ãƒã‚¿ãƒ¼ãŒã€ã“ã®åŒºç”»ã«ã„ã‚‹ã‚¢ãƒã‚¿ãƒ¼ã«ä¼šã£ã¦ãƒãƒ£ãƒƒãƒˆã™ã‚‹ã“ã¨ã‚’許å¯ã—ã€ã‚ãªãŸã‚‚ãれらアãƒã‚¿ãƒ¼ã«ä¼šã£ã¦ãƒãƒ£ãƒƒãƒˆã§ãるよã†ã«ã—ã¾ã™ã€‚"/> <text name="landing_point"> @@ -459,12 +459,12 @@ <text name="Limit access to this parcel to:"> ã“ã®åŒºç”»ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ </text> - <check_box label="パブリックアクセスを許å¯ã™ã‚‹ [MATURITY]" name="public_access"/> + <check_box label="パブリックアクセスを許å¯ï¼ˆã“ã®ã‚ªãƒ—ションをオフã«ã™ã‚‹ã¨ç«‹å…¥ç¦æ¢ãƒ©ã‚¤ãƒ³ãŒä½œæˆã•ã‚Œã¾ã™ï¼‰" name="public_access"/> <text name="Only Allow"> - 次ã®ä½äººã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ï¼š + 次ã®ä½äººã«ã®ã¿ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ï¼š </text> - <check_box label="æ”¯æ‰•æƒ…å ±ç™»éŒ²æ¸ˆ [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="未確èªã®ä½äººã®ç«‹å…¥ã‚’ç¦æ¢ã—ã¾ã™ã€‚"/> - <check_box label="å¹´é½¢ç¢ºèª [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„ä½äººã®ç«‹å…¥ã‚’ç¦æ¢ã—ã¾ã™ã€‚ 詳ã—ã„æƒ…å ±ã¯ [SUPPORT_SITE] ã‚’ã”覧下ã•ã„。"/> + <check_box label="æ”¯æ‰•æƒ…æƒ…å ±ãŒç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="æ”¯æ‰•æƒ…å ±ãŒç™»éŒ²ã•ã‚Œã¦ã„ãªã„ã¨ã€ã“ã®åŒºç”»ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。詳細ã«ã¤ã„ã¦ã¯ã€[SUPPORT_SITE] ã‚’ã”覧ãã ã•ã„。"/> + <check_box label="年齢確èªãŒæ¸ˆã‚“ã§ã„ã‚‹ [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="ã“ã®åŒºç”»ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ã€å¹´é½¢ç¢ºèªã‚’済ã¾ã›ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚詳細ã«ã¤ã„ã¦ã¯ã€[SUPPORT_SITE] ã‚’ã”覧ãã ã•ã„。"/> <check_box label="グループã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ï¼š[GROUP]" name="GroupCheck" tool_tip="「一般ã€ã‚¿ãƒ–ã§ã€ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã—ã¦ãã ã•ã„。"/> <check_box label="å…¥å ´è¨±å¯ã‚’販売:" name="PassCheck" tool_tip="ã“ã®åŒºç”»ã¸ã®ä¸€æ™‚çš„ãªã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã—ã¾ã™ã€‚"/> <combo_box name="pass_combo"> diff --git a/indra/newview/skins/default/xui/ja/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/ja/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..2bada303ae --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_animation_anim_preview.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Anim Preview" title="ANIMATION.ANIM"> + <text name="name_label"> + åå‰ï¼š + </text> + <text name="description_label"> + 説明: + </text> + <button label="アップãƒãƒ¼ãƒ‰ï¼ˆL$[AMOUNT])" name="ok_btn"/> + <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_animation_bvh_preview.xml b/indra/newview/skins/default/xui/ja/floater_animation_bvh_preview.xml new file mode 100644 index 0000000000..f74bab3598 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_animation_bvh_preview.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Animation Preview"> + <floater.string name="failed_to_initialize"> + å‹•ãã‚’åˆæœŸåŒ–ã§ãã¾ã›ã‚“ã§ã—㟠+ </floater.string> + <floater.string name="anim_too_long"> + アニメーションファイルã®é•·ã•ã¯ [LENGTH] 秒ã§ã™ã€‚ + +アニメーションã®æœ€å¤§é•·ã¯ [MAX_LENGTH] 秒ã§ã™ã€‚ + </floater.string> + <floater.string name="failed_file_read"> + アニメーションファイルをèªã¿å–ã‚Œã¾ã›ã‚“。 + +[STATUS] + </floater.string> + <floater.string name="E_ST_OK"> + Ok + </floater.string> + <floater.string name="E_ST_EOF"> + ファイルã®çµ‚端ãŒä¸å®Œå…¨ã§ã™ã€‚ + </floater.string> + <floater.string name="E_ST_NO_CONSTRAINT"> + 制約定義をèªã¿å–ã‚Œã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_FILE"> + BVH ファイルを開ã‘ã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_HIER"> + HIERARCHY ヘッダーãŒç„¡åŠ¹ã§ã™ã€‚ + </floater.string> + <floater.string name="E_ST_NO_JOINT"> + ROOT ã¾ãŸã¯ JOINT ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_NAME"> + JOINT åã‚’å–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_OFFSET"> + OFFSET ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_CHANNELS"> + CHANNELS ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_ROTATION"> + å›žè»¢é †åºã‚’å–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_AXIS"> + 回転軸をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_MOTION"> + MOTION ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_FRAMES"> + フレーム数をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_FRAME_TIME"> + フレーム時間をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_POS"> + ä½ç½®ã®å€¤ã‚’å–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_ROT"> + 回転値をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_FILE"> + 変æ›ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ã‘ã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_HEADER"> + 変æ›ãƒ˜ãƒƒãƒ€ãƒ¼ã‚’èªã¿å–ã‚Œã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_NAME"> + 変æ›åã‚’èªã¿å–ã‚Œã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_IGNORE"> + 変æ›ç„¡è¦–値をèªã¿å–ã‚Œã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_RELATIVE"> + 変æ›ç›¸å¯¾å€¤ã‚’èªã¿å–ã‚Œã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_OUTNAME"> + å¤‰æ› outname 値をèªã¿å–ã‚Œã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_MATRIX"> + 変æ›è¡Œåˆ—ã‚’èªã¿å–ã‚Œã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGECHILD"> + Mergechild åã‚’å–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGEPARENT"> + Mergeparent åã‚’å–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_PRIORITY"> + priority 値をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_LOOP"> + loop 値をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEIN"> + easeln 値をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEOUT"> + easeOut 値をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_HAND"> + Hand morph 値をå–å¾—ã§ãã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_NO_XLT_EMOTE"> + emote åã‚’èªã¿ã¨ã‚Œã¾ã›ã‚“。 + </floater.string> + <floater.string name="E_ST_BAD_ROOT"> + ルートジョイントåãŒä¸æ£ã§ã™ã€‚「hipã€ã‚’使用ã—ã¦ãã ã•ã„。 + </floater.string> + <text name="name_label"> + åå‰ï¼š + </text> + <text name="description_label"> + 説明: + </text> + <spinner label="優先度" name="priority" tool_tip="ã“ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã§ã©ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’上書ãã§ãã‚‹ã‹ã‚’決ã‚ã¾ã™"/> + <check_box label="ループ" name="loop_check" tool_tip="ã“ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ループå†ç”Ÿã«ã—ã¾ã™"/> + <spinner label="イン(%)" name="loop_in_point" tool_tip="アニメーションã®ãƒ«ãƒ¼ãƒ—復帰点をè¨å®šã—ã¾ã™"/> + <spinner label="アウト(%)" name="loop_out_point" tool_tip="アニメーションã®ãƒ«ãƒ¼ãƒ—終了点をè¨å®šã—ã¾ã™"/> + <text name="hand_label"> + 手ã®ãƒãƒ¼ã‚º + </text> + <combo_box name="hand_pose_combo" tool_tip="アニメーションå†ç”Ÿä¸ã®æ‰‹ã®å‹•ãを決ã‚ã¾ã™"> + <combo_box.item label="広ã’ã‚‹" name="Spread"/> + <combo_box.item label="リラックス" name="Relaxed"/> + <combo_box.item label="指を指ã™ãƒ»ä¸¡æ‰‹" name="PointBoth"/> + <combo_box.item label="拳" name="Fist"/> + <combo_box.item label="リラックス・左" name="RelaxedLeft"/> + <combo_box.item label="指を指ã™ãƒ»å·¦" name="PointLeft"/> + <combo_box.item label="拳を上ã’る・左" name="FistLeft"/> + <combo_box.item label="リラックス・å³" name="RelaxedRight"/> + <combo_box.item label="指を指ã™ãƒ»å³" name="PointRight"/> + <combo_box.item label="拳を上ã’る・å³" name="FistRight"/> + <combo_box.item label="敬礼・å³" name="SaluteRight"/> + <combo_box.item label="タイピング" name="Typing"/> + <combo_box.item label="ピース・å³" name="PeaceRight"/> + </combo_box> + <text name="emote_label"> + 表情 + </text> + <combo_box name="emote_combo" tool_tip="アニメーションå†ç”Ÿä¸ã®é¡”ã®è¡¨æƒ…を決ã‚ã¾ã™"> + <item label="(ãªã—)" name="[None]" value=""/> + <item label="アーーーーー" name="Aaaaah" value="アーーーーー"/> + <item label="æれる" name="Afraid" value="æれる"/> + <item label="怒る" name="Angry" value="怒る"/> + <item label="満é¢ã®ç¬‘ã¿" name="BigSmile" value="満é¢ã®ç¬‘ã¿"/> + <item label="退屈" name="Bored" value="退屈"/> + <item label="æ³£ã" name="Cry" value="æ³£ã"/> + <item label="軽蔑" name="Disdain" value="軽蔑"/> + <item label="æ¥ãšã‹ã—ãŒã‚‹" name="Embarrassed" value="æ¥ãšã‹ã—ãŒã‚‹"/> + <item label="ã—ã‹ã‚ã£é¢" name="Frown" value="ã—ã‹ã‚ã£é¢"/> + <item label="ã‚ス" name="Kiss" value="ã‚ス"/> + <item label="笑ã†" name="Laugh" value="笑ã†"/> + <item label="ã‚€ã‹ã¤ã" name="Plllppt" value="ã‚€ã‹ã¤ã"/> + <item label="嫌悪感" name="Repulsed" value="嫌悪感"/> + <item label="悲ã—ã„" name="Sad" value="悲ã—ã„"/> + <item label="è‚©ã‚’ã™ãã‚ã‚‹" name="Shrug" value="è‚©ã‚’ã™ãã‚ã‚‹"/> + <item label="微笑む" name="Smile" value="微笑む"/> + <item label="é©šã" name="Surprise" value="é©šã"/> + <item label="ウィンク" name="Wink" value="ウィンク"/> + <item label="心é…ã™ã‚‹" name="Worry" value="心é…ã™ã‚‹"/> + </combo_box> + <text name="preview_label"> + プレビューä¸ã®å‹•ä½œ + </text> + <combo_box name="preview_base_anim" tool_tip="ã“れを使用ã—ã¦ã€ã‚¢ãƒã‚¿ãƒ¼ãŒä¸€èˆ¬çš„ãªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã‚’実行ã—ã¦ã„ã‚‹é–“ã«ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®å‹•ä½œã‚’テストã—ã¾ã™ã€‚"> + <item label="ç«‹ã¤" name="Standing" value="ç«‹ã¤"/> + <item label="æ©ã" name="Walking" value="æ©ã"/> + <item label="座る" name="Sitting" value="座る"/> + <item label="飛ã¶" name="Flying" value="飛ã¶"/> + </combo_box> + <spinner label="イーズイン(秒)" name="ease_in_time" tool_tip="アニメーションã®ãƒ–レンドイン時間(秒)"/> + <spinner label="イーズアウト(秒)" name="ease_out_time" tool_tip="アニメーションã®ãƒ–レンドアウト時間(秒)"/> + <button name="play_btn" tool_tip="アニメーションをå†ç”Ÿã™ã‚‹"/> + <button name="pause_btn" tool_tip="アニメーションを一時åœæ¢ã™ã‚‹"/> + <button name="stop_btn" tool_tip="アニメーションã®å†ç”Ÿã‚’åœæ¢ã™ã‚‹"/> + <text name="bad_animation_text"> + アニメーションファイルをèªã¿å–ã‚Œã¾ã›ã‚“。 + +Poser 4 ã‹ã‚‰ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—㟠BVH ファイルをãŠå‹§ã‚ã—ã¾ã™ã€‚ + </text> + <button label="アップãƒãƒ¼ãƒ‰ï¼ˆL$[AMOUNT])" name="ok_btn"/> + <button label="å–り消ã—" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml index 504cea5931..11f223ade6 100644 --- a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml @@ -2,6 +2,6 @@ <floater name="chat_bar" title="è¿‘ãã®ãƒãƒ£ãƒƒãƒˆ"> <panel name="bottom_panel"> <line_editor label="ã“ã“をクリックã—ã¦ãƒãƒ£ãƒƒãƒˆã‚’開始ã—ã¾ã™ã€‚" name="chat_box" tool_tip="Enter ã‚ーを押ã—ã¦è©±ã—ã€Ctrl + Enter ã‚ーã§å«ã³ã¾ã™ã€‚"/> - <button name="show_nearby_chat" tool_tip="è¿‘ãã®ãƒãƒ£ãƒƒãƒˆãƒã‚°ã‚’表示・éžè¡¨ç¤º"/> + <button name="show_nearby_chat" tool_tip="è¿‘ãã®ãƒãƒ£ãƒƒãƒˆãƒã‚°ã‚’表示ï¼éžè¡¨ç¤º"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml index 725214086a..c01c46211e 100644 --- a/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="item properties" title="æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ã®ãƒ—ãƒãƒ‘ティ"> +<floater name="item properties" title="インベントリアイテムã®ãƒ—ãƒãƒ‘ティ"> <floater.string name="unknown"> (ä¸æ˜Žï¼‰ </floater.string> @@ -24,11 +24,11 @@ <text name="LabelCreatorTitle"> クリエーター </text> - <button label="æƒ…å ±" label_selected="" name="BtnCreator"/> + <button label="プãƒãƒ•ã‚£ãƒ¼ãƒ«..." label_selected="" name="BtnCreator"/> <text name="LabelOwnerTitle"> オーナー: </text> - <button label="æƒ…å ±" label_selected="" name="BtnOwner"/> + <button label="プãƒãƒ•ã‚£ãƒ¼ãƒ«..." label_selected="" name="BtnOwner"/> <text name="LabelAcquiredTitle"> 入手日時: </text> diff --git a/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml index 47d57da031..af96edda79 100644 --- a/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory Finder" title="最近å–å¾—ã—ãŸæŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ "> +<floater name="Inventory Finder" title="インベントリ最近å–å¾—ã—ãŸã‚¢ã‚¤ãƒ†ãƒ "> <check_box label="アニメーション" name="check_animation"/> <check_box label="コーリング・カード" name="check_calling_card"/> <check_box label="æœ" name="check_clothing"/> diff --git a/indra/newview/skins/default/xui/ja/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/ja/floater_merchant_outbox.xml new file mode 100644 index 0000000000..c59a3dc0ab --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_merchant_outbox.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_merchant_outbox" title="マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹"> + <string name="OutboxFolderCount1"> + 1 個ã®ãƒ•ã‚©ãƒ«ãƒ€ + </string> + <string name="OutboxFolderCountN"> + [NUM] 個ã®ãƒ•ã‚©ãƒ«ãƒ€ + </string> + <string name="OutboxImporting"> + フォルダをé€ä¿¡ä¸... + </string> + <string name="OutboxInitializing"> + åˆæœŸåŒ–ä¸... + </string> + <panel label=""> + <panel> + <panel name="outbox_inventory_placeholder_panel"> + <text name="outbox_inventory_placeholder_title"> + ãƒãƒ¼ãƒ‰ä¸... + </text> + </panel> + </panel> + <panel> + <button label="マーケットプレイスã«é€ä¿¡" name="outbox_import_btn" tool_tip="自分ã®ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイス店é ã«ç§»å‹•"/> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_model_wizard.xml b/indra/newview/skins/default/xui/ja/floater_model_wizard.xml deleted file mode 100644 index 6aaa9a42a5..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="header_panel"> - <text name="header_text"> - モデルファイルをé¸æŠž - </text> - </panel> - <panel name="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="header_panel"> - <text name="header_text"> - モデルを最é©åŒ– - </text> - </panel> - <text name="description"> - パフォーマンスをé‡è¦–ã—ã¦ãƒ¢ãƒ‡ãƒ«ã‚’最é©åŒ–ã—ã¾ã—ãŸã€‚å¿…è¦ã«å¿œã˜ã¦èª¿æ•´ã—ã¦ãã ã•ã„。 - </text> - <panel name="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="header_panel"> - <text name="header_text"> - 物ç†ä½œç”¨ã®èª¿æ•´ - </text> - </panel> - <text name="description"> - モデルã®å¤–æ®»æ§‹é€ ã®ã‚·ã‚§ã‚¤ãƒ—ã¯å¼Šç¤¾ãŒä½œæˆã—ã¾ã™ã€‚モデルã®ç›®çš„ã«å¿œã˜ã¦ã‚·ã‚§ã‚¤ãƒ—ã®è©³ç´°åº¦ã‚’調整ã—ã¦ãã ã•ã„。 - </text> - <panel name="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="header_panel"> - <text name="header_text"> - ç¢ºèª - </text> - </panel> - <panel name="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="header_panel"> - <text name="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_my_inventory.xml b/indra/newview/skins/default/xui/ja/floater_my_inventory.xml index c6a789b63b..d708fc3dec 100644 --- a/indra/newview/skins/default/xui/ja/floater_my_inventory.xml +++ b/indra/newview/skins/default/xui/ja/floater_my_inventory.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_my_inventory" title="æŒã¡ç‰©"/> +<floater name="floater_my_inventory" title="インベントリ"/> diff --git a/indra/newview/skins/default/xui/ja/floater_object_weights.xml b/indra/newview/skins/default/xui/ja/floater_object_weights.xml index 3bd9b6b069..d727a268fb 100644 --- a/indra/newview/skins/default/xui/ja/floater_object_weights.xml +++ b/indra/newview/skins/default/xui/ja/floater_object_weights.xml @@ -6,7 +6,7 @@ <text name="objects_label" value="オブジェクト"/> <text name="prims" value="--"/> <text name="prims_label" value="プリム"/> - <text name="weights_of_selected_text" value="é¸æŠžæ¸ˆã¿é …ç›®ã®ã‚¦ã‚¨ã‚¤ãƒˆ"/> + <text name="weights_of_selected_text" value="é¸æŠžæ¸ˆã¿ã‚¢ã‚¤ãƒ†ãƒ ã®ã‚¦ã‚¨ã‚¤ãƒˆ"/> <text name="download" value="--"/> <text name="download_label" value="ダウンãƒãƒ¼ãƒ‰"/> <text name="physics" value="--"/> diff --git a/indra/newview/skins/default/xui/ja/floater_openobject.xml b/indra/newview/skins/default/xui/ja/floater_openobject.xml index bd1b650f98..af02ffedda 100644 --- a/indra/newview/skins/default/xui/ja/floater_openobject.xml +++ b/indra/newview/skins/default/xui/ja/floater_openobject.xml @@ -3,6 +3,6 @@ <text name="object_name"> [DESC]: </text> - <button label="æŒã¡ç‰©ã«ã‚³ãƒ”ー" label_selected="æŒã¡ç‰©ã«ã‚³ãƒ”ー" name="copy_to_inventory_button"/> + <button label="インベントリã«ã‚³ãƒ”ー" label_selected="インベントリã«ã‚³ãƒ”ー" name="copy_to_inventory_button"/> <button label="コピーã—ã¦è£…ç€" label_selected="コピーã—ã¦è£…ç€" name="copy_and_wear_button"/> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_people.xml b/indra/newview/skins/default/xui/ja/floater_people.xml index 08bee88103..b180658ab7 100644 --- a/indra/newview/skins/default/xui/ja/floater_people.xml +++ b/indra/newview/skins/default/xui/ja/floater_people.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="floater_people" title="人"> <panel_container name="main_panel"> - <panel label="ã‚°ãƒ«ãƒ¼ãƒ—æƒ…å ±" name="panel_group_info_sidetray"/> + <panel label="グループプãƒãƒ•ã‚£ãƒ¼ãƒ«" name="panel_group_info_sidetray"/> <panel label="ブãƒãƒƒã‚¯ã•ã‚ŒãŸä½äººã¨ã‚ªãƒ–ジェクト" name="panel_block_list_sidetray"/> </panel_container> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_preview_animation.xml b/indra/newview/skins/default/xui/ja/floater_preview_animation.xml index 4fc59e16d3..a3042f66ea 100644 --- a/indra/newview/skins/default/xui/ja/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/ja/floater_preview_animation.xml @@ -6,6 +6,6 @@ <text name="desc txt"> 説明: </text> - <button label="インワールドã§å†ç”Ÿ" label_selected="åœæ¢" name="Anim play btn" tool_tip="他人ã«ã‚‚見ãˆã‚‹ã‚ˆã†ã«å†ç”Ÿã—ã¾ã™"/> - <button label="ãƒãƒ¼ã‚«ãƒ«å†ç”Ÿ" label_selected="åœæ¢" name="Anim audition btn" tool_tip="自分ã ã‘ãŒè¦‹ãˆã‚‹ã‚ˆã†ã«å†ç”Ÿã—ã¾ã™"/> + <button label="インワールドã§å†ç”Ÿ" label_selected="åœæ¢" name="Inworld" tool_tip="他人ã«è¦‹ãˆã‚‹ã‚ˆã†ã«å†ç”Ÿ"/> + <button label="ãƒãƒ¼ã‚«ãƒ«å†ç”Ÿ" label_selected="åœæ¢" name="Locally" tool_tip="自分ã ã‘ãŒè¦‹ãˆã‚‹ã‚ˆã†ã«å†ç”Ÿ"/> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_preview_texture.xml b/indra/newview/skins/default/xui/ja/floater_preview_texture.xml index 6ea1d79cfc..4617fd1d92 100644 --- a/indra/newview/skins/default/xui/ja/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/ja/floater_preview_texture.xml @@ -4,7 +4,7 @@ テクスãƒãƒ£ï¼š [NAME] </floater.string> <floater.string name="Copy"> - æŒã¡ç‰©ã«ã‚³ãƒ”ー + インベントリã«ã‚³ãƒ”ー </floater.string> <text name="desc txt"> 説明: diff --git a/indra/newview/skins/default/xui/ja/floater_snapshot.xml b/indra/newview/skins/default/xui/ja/floater_snapshot.xml index cf4732a68e..f145a2e8b8 100644 --- a/indra/newview/skins/default/xui/ja/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/ja/floater_snapshot.xml @@ -10,7 +10,7 @@ 投稿 </string> <string name="inventory_progress_str"> - æŒã¡ç‰©ã«ä¿å˜ + インベントリã«ä¿å˜ </string> <string name="local_progress_str"> コンピュータã«ä¿å˜ @@ -22,7 +22,7 @@ メールãŒé€ä¿¡ã•ã‚Œã¾ã—㟠</string> <string name="inventory_succeeded_str"> - æŒã¡ç‰©ã«ä¿å˜ã•ã‚Œã¾ã—㟠+ インベントリã«ä¿å˜ã•ã‚Œã¾ã—㟠</string> <string name="local_succeeded_str"> コンピュータã«ä¿å˜ã•ã‚Œã¾ã—㟠@@ -34,7 +34,7 @@ メールをé€ä¿¡ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ </string> <string name="inventory_failed_str"> - æŒã¡ç‰©ã«ä¿å˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ + インベントリã«ä¿å˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ </string> <string name="local_failed_str"> コンピュータã«ä¿å˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ diff --git a/indra/newview/skins/default/xui/ja/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/ja/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..31b5bbd3bf --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_test_layout_stacks.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="レイアウトスタックテスト"/> diff --git a/indra/newview/skins/default/xui/ja/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/ja/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..40fd8e9f93 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_test_text_vertical_aligment.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="テスト用ウィンドウ"/> diff --git a/indra/newview/skins/default/xui/ja/floater_tools.xml b/indra/newview/skins/default/xui/ja/floater_tools.xml index 8eddf55a44..2d12a5e56a 100644 --- a/indra/newview/skins/default/xui/ja/floater_tools.xml +++ b/indra/newview/skins/default/xui/ja/floater_tools.xml @@ -1,5 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="toolbox floater" short_title="制作ツール" title=""> + <floater.string name="grid_screen_text"> + ç”»é¢ + </floater.string> + <floater.string name="grid_local_text"> + ãƒãƒ¼ã‚«ãƒ« + </floater.string> + <floater.string name="grid_world_text"> + 世界 + </floater.string> + <floater.string name="grid_reference_text"> + リファレンス + </floater.string> + <floater.string name="grid_attachment_text"> + アタッãƒãƒ¡ãƒ³ãƒˆ + </floater.string> <floater.string name="status_rotate"> 色ã®ä»˜ã„ãŸãƒãƒ³ãƒ‰ã‚’ドラッグã—ã¦ã‚ªãƒ–ジェクトを回転 </floater.string> @@ -63,7 +78,12 @@ </text> <check_box initial_value="true" label="テクスãƒãƒ£ã‚’引ã延ã°ã™" name="checkbox stretch textures"/> <check_box initial_value="true" label="スナップ" name="checkbox snap to grid"/> - <button label="オプション..." label_selected="オプション" name="Options..." tool_tip="グリッドオプションを表示ã—ã¾ã™"/> + <combo_box name="combobox grid mode" tool_tip="オブジェクトã®é…ç½®ã«ä½¿ã†ã‚°ãƒªãƒƒãƒ‰ãƒ«ãƒ¼ãƒ©ã®ç¨®é¡žã‚’é¸æŠž"> + <combo_box.item label="世界" name="World"/> + <combo_box.item label="ãƒãƒ¼ã‚«ãƒ«" name="Local"/> + <combo_box.item label="リファレンス" name="Reference"/> + </combo_box> + <button label="" label_selected="オプション" name="Options..." tool_tip="グリッドオプションを表示ã—ã¾ã™"/> <button label="" label_selected="" name="ToolCube" tool_tip="ã‚ューブ"/> <button label="" label_selected="" name="ToolPrism" tool_tip="プリズム"/> <button label="" label_selected="" name="ToolPyramid" tool_tip="ピラミッド"/> diff --git a/indra/newview/skins/default/xui/ja/floater_voice_effect.xml b/indra/newview/skins/default/xui/ja/floater_voice_effect.xml index 801b7a9db0..ee675e143b 100644 --- a/indra/newview/skins/default/xui/ja/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/ja/floater_voice_effect.xml @@ -42,13 +42,16 @@ <string name="effect_Demon"> デーモン </string> + <string name="effect_Female Elf"> + 女性ã®ã‚¨ãƒ«ãƒ• + </string> <string name="effect_Flirty"> æ°—ã®ã‚ã‚Šãã†ãª </string> <string name="effect_Foxy"> é…惑的 </string> - <string name="effect_Halloween_2010_Bonus"> + <string name="effect_Halloween 2010 Bonus"> ãƒãƒã‚¦ã‚£ãƒ³_2010_ボーナス </string> <string name="effect_Helium"> @@ -57,9 +60,18 @@ <string name="effect_Husky"> ãƒã‚¹ã‚ー </string> + <string name="effect_Husky Whisper"> + スモーã‚ーウィスパー + </string> <string name="effect_Intercom"> インターホン </string> + <string name="effect_Julia"> + ジュリア + </string> + <string name="effect_Lo Lilt"> + 軽快 + </string> <string name="effect_Macho"> マッãƒãƒ§ </string> @@ -69,6 +81,9 @@ <string name="effect_Mini"> ミニ </string> + <string name="effect_Model"> + モデル + </string> <string name="effect_Nano"> ナノ </string> @@ -90,6 +105,9 @@ <string name="effect_Roxanne"> ãƒã‚¯ã‚µãƒ³ </string> + <string name="effect_Rumble"> + ランブル + </string> <string name="effect_Sabrina"> サブリナ </string> @@ -102,6 +120,9 @@ <string name="effect_Shorty"> ãƒãƒ“ </string> + <string name="effect_Smaller"> + å°ã•ã‚ + </string> <string name="effect_Sneaky"> コソコソ </string> diff --git a/indra/newview/skins/default/xui/ja/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/ja/menu_inspect_object_gear.xml index 2edade70bf..5a0519ba19 100644 --- a/indra/newview/skins/default/xui/ja/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/ja/menu_inspect_object_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<menu name="Gear Menu"> +<toggleable_menu name="Gear Menu"> <menu_item_call label="触る" name="touch"/> <menu_item_call label="座る" name="sit"/> <menu_item_call label="支払ã†" name="pay"/> @@ -12,7 +12,8 @@ <menu_item_call label="è¿½åŠ " name="add"/> <menu_item_call label="å ±å‘Š" name="report"/> <menu_item_call label="ブãƒãƒƒã‚¯" name="block"/> + <menu_item_call label="ブãƒãƒƒã‚¯è§£é™¤" name="unblock"/> <menu_item_call label="ズームイン" name="zoom_in"/> <menu_item_call label="削除" name="remove"/> <menu_item_call label="詳細" name="more_info"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ja/menu_inventory.xml b/indra/newview/skins/default/xui/ja/menu_inventory.xml index 9449e61274..d1893a0fc8 100644 --- a/indra/newview/skins/default/xui/ja/menu_inventory.xml +++ b/indra/newview/skins/default/xui/ja/menu_inventory.xml @@ -59,6 +59,7 @@ <menu_item_call label="プãƒãƒ‘ティ" name="Properties"/> <menu_item_call label="åå‰ã‚’変更ã™ã‚‹" name="Rename"/> <menu_item_call label="UUID をコピーã™ã‚‹" name="Copy Asset UUID"/> + <menu_item_call label="カット" name="Cut"/> <menu_item_call label="コピー" name="Copy"/> <menu_item_call label="貼り付ã‘" name="Paste"/> <menu_item_call label="リンクを貼り付ã‘ã‚‹" name="Paste As Link"/> @@ -84,6 +85,6 @@ <menu_item_call label="è¿½åŠ " name="Wearable Add"/> <menu_item_call label="å–り外ã™" name="Take Off"/> <menu_item_call label="マーãƒãƒ£ãƒ³ãƒˆã®ã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«ã‚³ãƒ”ー" name="Merchant Copy"/> - <menu_item_call label="マーãƒãƒ£ãƒ³ãƒˆã®ã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«ç§»å‹•" name="Merchant Move"/> + <menu_item_call label="マーケットプレイスã«é€ä¿¡" name="Marketplace Send"/> <menu_item_call label="ï¼ï¼ã‚ªãƒ—ションãªã—ï¼ï¼" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/ja/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/ja/menu_inventory_gear_default.xml index 1f425df83c..f38dbc71a8 100644 --- a/indra/newview/skins/default/xui/ja/menu_inventory_gear_default.xml +++ b/indra/newview/skins/default/xui/ja/menu_inventory_gear_default.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <toggleable_menu name="menu_gear_default"> - <menu_item_call label="æ–°ã—ã„æŒã¡ç‰©ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦" name="new_window"/> + <menu_item_call label="æ–°ã—ã„インベントリウィンドウ" name="new_window"/> <menu_item_check label="åå‰ã§ä¸¦ã¹æ›¿ãˆ" name="sort_by_name"/> <menu_item_check label="æ–°ã—ã„é †ã«ä¸¦ã¹æ›¿ãˆ" name="sort_by_recent"/> <menu_item_check label="フォルダを常ã«åå‰é †ã«ä¸¦ã¹ã‚‹" name="sort_folders_by_name"/> diff --git a/indra/newview/skins/default/xui/ja/menu_login.xml b/indra/newview/skins/default/xui/ja/menu_login.xml index 4c88f17f3d..ab6d9e3546 100644 --- a/indra/newview/skins/default/xui/ja/menu_login.xml +++ b/indra/newview/skins/default/xui/ja/menu_login.xml @@ -17,8 +17,8 @@ <menu_item_call label="ウィンドウã®ã‚µã‚¤ã‚ºã‚’è¨å®š..." name="Set Window Size..."/> <menu_item_call label="利用è¦ç´„を表示" name="TOS"/> <menu_item_call label="クリティカルメッセージを表示" name="Critical"/> - <menu_item_call label="メディアブラウザã®ãƒ†ã‚¹ãƒˆ" name="Web Browser Test"/> <menu_item_call label="Web コンテンツフãƒãƒ¼ã‚¿ãƒ¼ã®ãƒ‡ãƒãƒƒã‚°ãƒ†ã‚¹ãƒˆ" name="Web Content Floater Debug Test"/> + <menu label="ãƒã‚°ãƒ¬ãƒ™ãƒ«ã‚’è¨å®š" name="Set Logging Level"/> <menu_item_check label="グリッドピッカーを表示ã™ã‚‹" name="Show Grid Picker"/> <menu_item_call label="通知コンソールを表示ã™ã‚‹" name="Show Notifications Console"/> </menu> diff --git a/indra/newview/skins/default/xui/ja/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/ja/menu_places_gear_folder.xml index e64f97fda5..c455204722 100644 --- a/indra/newview/skins/default/xui/ja/menu_places_gear_folder.xml +++ b/indra/newview/skins/default/xui/ja/menu_places_gear_folder.xml @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <toggleable_menu name="menu_folder_gear"> <menu_item_call label="ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‚’è¿½åŠ " name="add_landmark"/> <menu_item_call label="ãƒ•ã‚©ãƒ«ãƒ€ã‚’è¿½åŠ " name="add_folder"/> - <menu_item_call label="商å“を復元" name="restore_item"/> + <menu_item_call label="アイテムを復元" name="restore_item"/> <menu_item_call label="切りå–ã‚Š" name="cut"/> <menu_item_call label="コピー" name="copy_folder"/> <menu_item_call label="貼り付ã‘" name="paste"/> diff --git a/indra/newview/skins/default/xui/ja/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/ja/menu_places_gear_landmark.xml index f416b5b1f6..579f2c2cbd 100644 --- a/indra/newview/skins/default/xui/ja/menu_places_gear_landmark.xml +++ b/indra/newview/skins/default/xui/ja/menu_places_gear_landmark.xml @@ -1,11 +1,11 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <toggleable_menu name="menu_ladmark_gear"> <menu_item_call label="テレãƒãƒ¼ãƒˆ" name="teleport"/> <menu_item_call label="ã‚‚ã£ã¨è©³ã—ã" name="more_info"/> <menu_item_call label="地図ã«è¡¨ç¤º" name="show_on_map"/> <menu_item_call label="ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‚’è¿½åŠ " name="add_landmark"/> <menu_item_call label="ãƒ•ã‚©ãƒ«ãƒ€ã‚’è¿½åŠ " name="add_folder"/> - <menu_item_call label="商å“を復元" name="restore_item"/> + <menu_item_call label="アイテムを復元" name="restore_item"/> <menu_item_call label="切りå–ã‚Š" name="cut"/> <menu_item_call label="ランドマークをコピー" name="copy_landmark"/> <menu_item_call label="SLurl をコピー" name="copy_slurl"/> diff --git a/indra/newview/skins/default/xui/ja/menu_url_inventory.xml b/indra/newview/skins/default/xui/ja/menu_url_inventory.xml index 7af2f9e2cd..147ab44a1b 100644 --- a/indra/newview/skins/default/xui/ja/menu_url_inventory.xml +++ b/indra/newview/skins/default/xui/ja/menu_url_inventory.xml @@ -1,6 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <context_menu name="Url Popup"> - <menu_item_call label="æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ を表示" name="show_item"/> + <menu_item_call label="インベントリアイテムを表示" name="show_item"/> <menu_item_call label="åå‰ã‚’クリップボードã«ã‚³ãƒ”ー" name="url_copy_label"/> <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/> </context_menu> diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml index ef3261f1d4..8496dfb1db 100644 --- a/indra/newview/skins/default/xui/ja/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml @@ -4,8 +4,8 @@ <menu_item_call label="プãƒãƒ•ã‚£ãƒ¼ãƒ«..." name="Profile"/> <menu_item_call label="容姿..." name="ChangeOutfit"/> <menu_item_call label="ã‚¢ãƒã‚¿ãƒ¼ã‚’é¸æŠž..." name="Avatar Picker"/> - <menu_item_check label="æŒã¡ç‰©..." name="Inventory"/> - <menu_item_call label="æ–°ã—ã„æŒã¡ç‰©ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦" name="NewInventoryWindow"/> + <menu_item_check label="インベントリ..." name="Inventory"/> + <menu_item_call label="æ–°ã—ã„インベントリウィンドウ" name="NewInventoryWindow"/> <menu_item_call label="å ´æ‰€..." name="Places"/> <menu_item_call label="ピック..." name="Picks"/> <menu_item_call label="カメラコントãƒãƒ¼ãƒ«..." name="Camera Controls"/> @@ -14,14 +14,14 @@ <menu_item_check label="飛ã¶" name="Fly"/> <menu_item_check label="常ã«èµ°ã‚‹" name="Always Run"/> <menu_item_call label="ç§ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’åœæ¢ã™ã‚‹" name="Stop Animating My Avatar"/> + <menu_item_call label="æ©è¡Œï¼èµ°è¡Œï¼é£›è¡Œ..." name="Walk / run / fly"/> </menu> <menu label="ãƒã‚°ã‚¤ãƒ³" name="Status"> <menu_item_call label="一時退å¸ä¸" name="Set Away"/> <menu_item_call label="å–ã‚Šè¾¼ã¿ä¸" name="Set Busy"/> </menu> - <menu_item_call label="管ç†è€…権é™ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆ" name="Request Admin Options"/> - <menu_item_call label="管ç†è€…ステータス解除" name="Leave Admin Options"/> - <menu_item_call label="L$ ã®è³¼å…¥" name="Buy and Sell L$"/> + <menu_item_call label="L$ ã®è³¼å…¥..." name="Buy and Sell L$"/> + <menu_item_call label="マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹..." name="MerchantOutbox"/> <menu_item_call label="マイアカウント..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=ja"/> </menu_item_call> @@ -63,11 +63,11 @@ <menu_item_check label="区画プãƒãƒ‘ティ" name="Parcel Properties"/> <menu_item_check label="アドãƒãƒ³ã‚¹ãƒ¡ãƒ‹ãƒ¥ãƒ¼" name="Show Advanced Menu"/> </menu> - <menu label="太陽" name="Environment Settings"> + <menu label="太陽" name="Sun"> <menu_item_call label="æ—¥ã®å‡º" name="Sunrise"/> <menu_item_call label="æ£åˆ" name="Noon"/> <menu_item_call label="日没" name="Sunset"/> - <menu_item_call label="深夜" name="Midnight"/> + <menu_item_call label="真夜ä¸" name="Midnight"/> <menu_item_call label="リージョンã®è¨å®šã‚’使用" name="Use Region Settings"/> </menu> <menu label="自然環境エディター" name="Environment Editor"> @@ -113,7 +113,7 @@ <menu_item_call label="è²·ã†" name="Menu Object Buy"/> <menu_item_call label="å–ã‚‹" name="Menu Object Take"/> <menu_item_call label="コピーをå–ã‚‹" name="Take Copy"/> - <menu_item_call label="「æŒã¡ç‰©ã€ã«ä¿å˜" name="Save Object Back to My Inventory"/> + <menu_item_call label="マイインベントリã«ä¿å˜" name="Save Object Back to My Inventory"/> <menu_item_call label="オブジェクトã®ä¸èº«ã«ä¿å˜" name="Save Object Back to Object Contents"/> <menu_item_call label="オブジェクトを返å´ã™ã‚‹" name="Return Object back to Owner"/> </menu> @@ -178,22 +178,22 @@ <menu_item_check label="一人称視点ã®ã¨ãã«åå—線を表示ã™ã‚‹" name="ShowCrosshairs"/> </menu> <menu label="レンダリング(種類)" name="Rendering Types"> - <menu_item_check label="シンプル" name="Simple"/> - <menu_item_check label="アルファ" name="Alpha"/> - <menu_item_check label="木" name="Tree"/> - <menu_item_check label="ã‚¢ãƒã‚¿ãƒ¼" name="Character"/> - <menu_item_check label="サーフェスパッãƒ" name="Surface Patch"/> - <menu_item_check label="空" name="Sky"/> - <menu_item_check label="æ°´" name="Water"/> - <menu_item_check label="地é¢" name="Ground"/> - <menu_item_check label="ボリューム" name="Volume"/> - <menu_item_check label="è‰" name="Grass"/> - <menu_item_check label="雲" name="Clouds"/> - <menu_item_check label="パーティクル" name="Particles"/> - <menu_item_check label="è¡çª" name="Bump"/> + <menu_item_check label="シンプル" name="Rendering Type Simple"/> + <menu_item_check label="アルファ" name="Rendering Type Alpha"/> + <menu_item_check label="木" name="Rendering Type Tree"/> + <menu_item_check label="ã‚¢ãƒã‚¿ãƒ¼" name="Rendering Type Character"/> + <menu_item_check label="サーフェスパッãƒ" name="Rendering Type Surface Patch"/> + <menu_item_check label="空" name="Rendering Type Sky"/> + <menu_item_check label="æ°´" name="Rendering Type Water"/> + <menu_item_check label="地é¢" name="Rendering Type Ground"/> + <menu_item_check label="å–引高" name="Rendering Type Volume"/> + <menu_item_check label="è‰" name="Rendering Type Grass"/> + <menu_item_check label="雲" name="Rendering Type Clouds"/> + <menu_item_check label="パーティクル" name="Rendering Type Particles"/> + <menu_item_check label="è¡çª" name="Rendering Type Bump"/> </menu> <menu label="レンダリング(機能)" name="Rendering Features"> - <menu_item_check label="UI" name="UI"/> + <menu_item_check label="UI" name="ToggleUI"/> <menu_item_check label="é¸æŠžæ¸ˆ" name="Selected"/> <menu_item_check label="ãƒã‚¤ãƒ©ã‚¤ãƒˆ" name="Highlighted"/> <menu_item_check label="ダイナミックテクスãƒãƒ£" name="Dynamic Textures"/> @@ -207,8 +207,6 @@ <menu_item_check label="マウスã®å¹³æ»‘化" name="Mouse Smoothing"/> <menu_item_call label="リリースã‚ー" name="Release Keys"/> <menu label="ショートカット" name="Shortcuts"> - <menu_item_call label="ç”»åƒ ï¼ˆL$ [COST] )..." name="Upload Image"/> - <menu_item_check label="検索" name="Search"/> <menu_item_check label="アドãƒãƒ³ã‚¹ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’表示 - レガシーã®ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆ" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="ウィンドウを閉ã˜ã‚‹" name="Close Window"/> <menu_item_call label="å…¨ã¦ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã‚‹" name="Close All Windows"/> @@ -217,13 +215,6 @@ <menu_item_check label="ジョイスティックフライカム" name="Joystick Flycam"/> <menu_item_call label="表示をリセットã™ã‚‹" name="Reset View"/> <menu_item_call label="最後ã®ç™ºè¨€è€…を見る" name="Look at Last Chatter"/> - <menu label="制作ツールをé¸æŠžã™ã‚‹" name="Select Tool"> - <menu_item_call label="焦点ツール" name="Focus"/> - <menu_item_call label="移動ツール" name="Move"/> - <menu_item_call label="編集ツール" name="Edit"/> - <menu_item_call label="作æˆãƒ„ール" name="Create"/> - <menu_item_call label="土地ツール" name="Land"/> - </menu> <menu_item_call label="ズームイン" name="Zoom In"/> <menu_item_call label="ズーム(デフォルト)" name="Zoom Default"/> <menu_item_call label="ズームアウト" name="Zoom Out"/> @@ -296,6 +287,7 @@ <menu_item_check label="レイã‚ャスト" name="Raycast"/> <menu_item_check label="風ã®ãƒ™ã‚¯ãƒˆãƒ«" name="Wind Vectors"/> <menu_item_check label="æç”»ã®è©³ç´°åº¦" name="rendercomplexity"/> + <menu_item_check label="添付アイテムã®ãƒã‚¤ãƒˆæ•°" name="attachment bytes"/> <menu_item_check label="スカルプト" name="Sculpt"/> </menu> <menu label="レンダリング" name="Rendering"> @@ -337,17 +329,16 @@ <menu_item_call label="記録開始" name="Start Record"/> <menu_item_call label="記録åœæ¢" name="Stop Record"/> </menu> - <menu label="世界" name="World"> + <menu label="世界" name="DevelopWorld"> <menu_item_check label="シムã®å¤ªé™½ã®è¨å®šã‚’無視ã™ã‚‹" name="Sim Sun Override"/> - <menu_item_check label="ビーコンを強調表示ã™ã‚‹" name="Cheesy Beacon"/> <menu_item_check label="固定ã•ã‚ŒãŸå¤©æ°—" name="Fixed Weather"/> - <menu_item_call label="リージョンオブジェクトã®ã‚ャッシュをダンプã™ã‚‹" name="Dump Region Object Cache"/> + <menu_item_call label="リージョンオブジェクトã®ã‚ャッシュをダンプ" name="Dump Region Object Cache"/> </menu> <menu label="UI" name="UI"> <menu_item_call label="メディアブラウザã®ãƒ†ã‚¹ãƒˆ" name="Web Browser Test"/> <menu_item_call label="Web コンテンツブラウザ" name="Web Content Browser"/> <menu_item_call label="SelectMgr をダンプ" name="Dump SelectMgr"/> - <menu_item_call label="æŒã¡ç‰©ã®å‡ºåŠ›" name="Dump Inventory"/> + <menu_item_call label="インベントリã®å‡ºåŠ›" name="Dump Inventory"/> <menu_item_call label="タイマーをダンプ" name="Dump Timers"/> <menu_item_call label="フォーカスホールダーをダンプ" name="Dump Focus Holder"/> <menu_item_call label="é¸æŠžã—ãŸã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆæƒ…å ±ã‚’ãƒ—ãƒªãƒ³ãƒˆ" name="Print Selected Object Info"/> @@ -371,11 +362,11 @@ </menu> <menu label="ã‚¢ãƒã‚¿ãƒ¼" name="Character"> <menu label="ベークドテクスãƒãƒ£ã‚’å–å¾—ã™ã‚‹" name="Grab Baked Texture"> - <menu_item_call label="çž³" name="Iris"/> - <menu_item_call label="é " name="Head"/> - <menu_item_call label="上åŠèº«" name="Upper Body"/> - <menu_item_call label="下åŠèº«" name="Lower Body"/> - <menu_item_call label="スカート" name="Skirt"/> + <menu_item_call label="çž³" name="Grab Iris"/> + <menu_item_call label="é " name="Grab Head"/> + <menu_item_call label="上åŠèº«" name="Grab Upper Body"/> + <menu_item_call label="下åŠèº«" name="Grab Lower Body"/> + <menu_item_call label="スカート" name="Grab Skirt"/> </menu> <menu label="ã‚ャラクターテスト" name="Character Tests"> <menu_item_call label="容姿を XML ã«ä¿å˜ã™ã‚‹" name="Appearance To XML"/> @@ -401,22 +392,30 @@ <menu_item_call label="ãƒãƒ¼ã‚«ãƒ«ãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’ダンプ" name="Dump Local Textures"/> </menu> <menu_item_check label="HTTP Texture" name="HTTP Textures"/> - <menu_item_check label="HTTP æŒã¡ç‰©" name="HTTP Inventory"/> + <menu_item_check label="HTTP インベントリ" name="HTTP Inventory"/> <menu_item_call label="圧縮画åƒ" name="Compress Images"/> + <menu_item_call label="Visual Leak Detector を有効ã«ã™ã‚‹" name="Enable Visual Leak Detector"/> <menu_item_check label="デãƒãƒƒã‚°ç”¨ã®ãƒŸãƒ‹ãƒ€ãƒ³ãƒ—を出力ã™ã‚‹" name="Output Debug Minidump"/> <menu_item_check label="次回ã®èµ·å‹•æ™‚ã«ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’表示ã™ã‚‹" name="Console Window"/> + <menu label="ãƒã‚°ãƒ¬ãƒ™ãƒ«ã‚’è¨å®š" name="Set Logging Level"> + <menu_item_check label="デãƒãƒƒã‚°" name="Debug"/> + <menu_item_check label="æƒ…å ±" name="Info"/> + <menu_item_check label="è¦å‘Š" name="Warning"/> + <menu_item_check label="エラー" name="Error"/> + <menu_item_check label="ãªã—" name="None"/> + </menu> <menu_item_call label="管ç†è€…ステータスã®å‘¼ã³å‡ºã—" name="Request Admin Options"/> <menu_item_call label="管ç†è€…ステータス解除" name="Leave Admin Options"/> <menu_item_check label="管ç†è€…メニューを表示ã™ã‚‹" name="View Admin Options"/> </menu> <menu label="管ç†è€…" name="Admin"> - <menu label="Object"> - <menu_item_call label="コピーをå–ã‚‹" name="Take Copy"/> + <menu label="オブジェクト" name="AdminObject"> + <menu_item_call label="コピーをå–ã‚‹" name="Admin Take Copy"/> <menu_item_call label="ç§ã‚’所有者ã«ã™ã‚‹" name="Force Owner To Me"/> - <menu_item_call label="所有者権é™ã‚’実行ã™ã‚‹" name="Force Owner Permissive"/> + <menu_item_call label="所有者権é™ã®å®Ÿè¡Œ" name="Force Owner Permissive"/> <menu_item_call label="削除" name="Delete"/> <menu_item_call label="ãƒãƒƒã‚¯" name="Lock"/> - <menu_item_call label="アセット ID ã‚’å–å¾—ã™ã‚‹" name="Get Assets IDs"/> + <menu_item_call label="アセット ID ã‚’å–å¾—" name="Get Assets IDs"/> </menu> <menu label="区画" name="Parcel"> <menu_item_call label="ç§ã‚’所有者ã«ã™ã‚‹" name="Owner To Me"/> @@ -447,7 +446,7 @@ <menu_item_call label="物ç†ä½œç”¨" name="Physics"/> <menu_item_call label="ã™ã¹ã¦ã®è¡£é¡ž" name="All Clothes"/> </menu> - <menu label="ヘルプ" name="Help"> + <menu label="ヘルプ" name="DeprecatedHelp"> <menu_item_call label="リンデン公å¼ãƒ–ãƒã‚°" name="Official Linden Blog"/> <menu_item_call label="スクリプトãƒãƒ¼ã‚¿ãƒ«" name="Scripting Portal"/> <menu label="ãƒã‚°ã®å ±å‘Š" name="Bug Reporting"> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index 20468c8c2a..7bf8a7b8be 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -85,17 +85,38 @@ <usetemplate canceltext="ã‚ャンセル" name="yesnocancelbuttons" notext="ä¿å˜ã—ãªã„" yestext="ä¿å˜"/> </notification> <notification name="ConfirmNoCopyToOutbox"> - マーãƒãƒ£ãƒ³ãƒˆã®ã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«ã“れをコピーã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã™ã€‚次ã®ã‚¢ã‚¤ãƒ†ãƒ を移動ã—ã¾ã™ã‹ï¼Ÿ -[ITEM_NAME] - <usetemplate name="okcancelbuttons" notext="ã„ã„ãˆ" yestext="ã¯ã„"/> + ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã® 1 ã¤ã¾ãŸã¯è¤‡æ•°ã‚’マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«ã‚³ãƒ”ーã™ã‚‹è¨±å¯ãŒã‚ã‚Šã¾ã›ã‚“。移動ã™ã‚‹ã‹ã€ç½®ã去りã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã€‚ + <usetemplate name="okcancelbuttons" notext="アイテムを移動ã—ãªã„" yestext="アイテムを移動"/> + </notification> + <notification name="OutboxFolderCreated"> + マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã®æœ€ä¸Šä½ã«è»¢é€ã—ãŸå„アイテムã«ã¤ãã€ãã‚Œãžã‚Œ 1 ã¤ã®æ–°ã—ã„フォルダãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚ + <usetemplate ignoretext="æ–°ã—ã„フォルダãŒãƒžãƒ¼ãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹å†…ã«ä½œæˆã•ã‚Œã¾ã—ãŸ" name="okignore" yestext="OK"/> + </notification> + <notification name="OutboxImportComplete"> + æˆåŠŸ + +マーケットプレイスã«æ£å¸¸ã«é€ä¿¡ã•ã‚ŒãŸã™ã¹ã¦ã®ãƒ•ã‚©ãƒ«ãƒ€ + <usetemplate ignoretext="マーケットプレイスã«é€ä¿¡ã•ã‚ŒãŸã™ã¹ã¦ã®ãƒ•ã‚©ãƒ«ãƒ€" name="okignore" yestext="OK"/> + </notification> + <notification name="OutboxImportHadErrors"> + 一部ã®ãƒ•ã‚©ãƒ«ãƒ€ã¯è»¢é€ã•ã‚Œã¾ã›ã‚“ã§ã—㟠+ +一部ã®ãƒ•ã‚©ãƒ«ãƒ€ãŒãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã«é€ä¿¡ã•ã‚ŒãŸã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã“れらã®ãƒ•ã‚©ãƒ«ãƒ€ã¯ã¾ã マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹å†…ã«ã‚ã‚Šã¾ã™ã€‚ + +詳細ã«ã¤ã„ã¦ã¯ã€[[MARKETPLACE_IMPORTS_URL] エラーãƒã‚°]ã‚’ã”覧ãã ã•ã„。 + <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="OutboxUploadComplete"> - マーケットプレイスã¸ã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ãŒå®Œäº†ã—ã¾ã—ãŸã€‚ - <usetemplate name="okbutton" yestext="ã‚„ã£ãŸã‚ï¼"/> + <notification name="OutboxImportFailed"> + 転é€ã«å¤±æ•— + +システムã¾ãŸã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã‚¨ãƒ©ãƒ¼ã®ãŸã‚ã€ãƒ•ã‚©ãƒ«ãƒ€ã¯ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã«é€ä¿¡ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚後ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。 + <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="OutboxUploadHadErrors"> - マーケットプレイスã¸ã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã®å®Œäº†æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚アウトボックスã®å•é¡Œã‚’解決ã—ã¦ã€ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚ - <usetemplate name="okbutton" yestext="å†ãƒˆãƒ©ã‚¤ï¼"/> + <notification name="OutboxInitFailed"> + マーケットプレイスã®åˆæœŸåŒ–ã«å¤±æ•— + +システムã¾ãŸã¯ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ã‚¨ãƒ©ãƒ¼ã®ãŸã‚ã€ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã®åˆæœŸåŒ–ã«å¤±æ•—ã—ã¾ã—ãŸã€‚後ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。 + <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="CompileQueueSaveText"> 次ã®ç†ç”±ã§ã€ã‚¹ã‚¯ãƒªãƒ—ト用テã‚ストã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰æ™‚ã«å•é¡ŒãŒèµ·ã“ã‚Šã¾ã—ãŸã€‚ @@ -243,7 +264,7 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã <usetemplate name="okcancelbuttons" notext="ã‚ャンセル" yestext="OK"/> </notification> <notification name="ReturnObjectsDeededToGroup"> - ã“ã®åŒºç”»ã®ã‚°ãƒ«ãƒ¼ãƒ— [NAME] 共有ã®ã™ã¹ã¦ã®ã‚ªãƒ–ジェクトをã€ä»¥å‰ã®æ‰€æœ‰è€…ã®ã€ŒæŒã¡ç‰©ã€ã«æˆ»ãã†ã¨ã—ã¦ã„ã¾ã™ã€‚ + ã“ã®åŒºç”»ã®ã‚°ãƒ«ãƒ¼ãƒ— [NAME] 共有ã®ã™ã¹ã¦ã®ã‚ªãƒ–ジェクトをã€ä»¥å‰ã®æ‰€æœ‰è€…ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«æˆ»ãã†ã¨ã—ã¦ã„ã¾ã™ã€‚ æ“作を続行ã—ã¾ã™ã‹ï¼Ÿ *è¦å‘Š* ã“ã‚Œã«ã‚ˆã‚Šã€ @@ -254,21 +275,21 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã <notification name="ReturnObjectsOwnedByUser"> ã“ã®åŒºç”»ã§ã€ ä½äºº [NAME] ãŒæ‰€æœ‰ã™ã‚‹å…¨ã¦ã®ã‚ªãƒ–ジェクトを -本人ã®ã€ŒæŒã¡ç‰©ã€ã«æœ¬å½“ã«è¿”å´ã—ã¦ã‚‚よã„ã§ã™ã‹ï¼Ÿ +本人ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«æœ¬å½“ã«è¿”å´ã—ã¦ã‚‚よã„ã§ã™ã‹ï¼Ÿ オブジェクト: [N] <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/> </notification> <notification name="ReturnObjectsOwnedBySelf"> ã“ã®åœŸåœ°åŒºç”»å†…ã«ã‚ã‚‹ã€ã‚ãªãŸãŒæ‰€æœ‰ã™ã‚‹ã™ã¹ã¦ã®ã‚ªãƒ–ジェクトを〠-ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã«æˆ»ãã†ã¨ã—ã¦ã„ã¾ã™ã€‚続ã‘ã¾ã™ã‹ï¼Ÿ +ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«æˆ»ãã†ã¨ã—ã¦ã„ã¾ã™ã€‚続ã‘ã¾ã™ã‹ï¼Ÿ オブジェクト: [N] <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/> </notification> <notification name="ReturnObjectsNotOwnedBySelf"> ã“ã®åœŸåœ°åŒºç”»å†…ã«ã‚ã‚‹ã€ã‚ãªãŸä»¥å¤–ãŒæ‰€æœ‰ã™ã‚‹ã™ã¹ã¦ã®ã‚ªãƒ–ジェクトを〠-ãã‚Œãžã‚Œã®æ‰€æœ‰è€…ã®ã€ŒæŒã¡ç‰©ã€ã«æˆ»ãã†ã¨ã—ã¦ã„ã¾ã™ã€‚ +ãã‚Œãžã‚Œã®æ‰€æœ‰è€…ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«æˆ»ãã†ã¨ã—ã¦ã„ã¾ã™ã€‚ æ“作を続行ã—ã¾ã™ã‹ï¼Ÿ グループã«è²æ¸¡ã•ã‚ŒãŸã€Œå†è²©ãƒ»ãƒ—レゼントå¯ã€ã®ã‚ªãƒ–ジェクトã¯ã€ä»¥å‰ã®æ‰€æœ‰è€…ã«è¿”å´ã•ã‚Œã¾ã™ã€‚ @@ -279,7 +300,7 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã </notification> <notification name="ReturnObjectsNotOwnedByUser"> ã“ã®åœŸåœ°åŒºç”»å†…ã«ã‚る〠-[NAME]以外ã«ã‚ˆã‚‹æ‰€æœ‰ã®ã‚ªãƒ–ジェクトをã™ã¹ã¦ãã‚Œãžã‚Œã®æ‰€æœ‰è€…ã®ã€ŒæŒã¡ç‰©ã€ã«è¿”å´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ +[NAME]以外ã«ã‚ˆã‚‹æ‰€æœ‰ã®ã‚ªãƒ–ジェクトをã™ã¹ã¦ãã‚Œãžã‚Œã®æ‰€æœ‰è€…ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«è¿”å´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ æ“作を続行ã—ã¾ã™ã‹ï¼Ÿã‚°ãƒ«ãƒ¼ãƒ—ã«è²æ¸¡ã•ã‚ŒãŸã€Œå†è²©ãƒ»ãƒ—レゼントå¯ã€ã®ã‚ªãƒ–ジェクトã¯ã€ä»¥å‰ã®æ‰€æœ‰è€…ã«è¿”å´ã•ã‚Œã¾ã™ã€‚ *è¦å‘Š* ã“ã‚Œã«ã‚ˆã‚Šã€ @@ -443,14 +464,14 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã ジェスãƒãƒ£ãƒ¼ã®ä¿å˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚å°‘ã—å¾…ã£ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。 </notification> <notification name="GestureSaveFailedObjectNotFound"> - ジェスãƒãƒ£ãƒ¼ã®ä¿å˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚オブジェクトã€ã¾ãŸã¯é–¢é€£ã™ã‚‹ã‚ªãƒ–ジェクトæŒã¡ç‰©ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + ジェスãƒãƒ£ãƒ¼ã®ä¿å˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚オブジェクトã€ã¾ãŸã¯é–¢é€£ã™ã‚‹ã‚ªãƒ–ジェクトインベントリãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 オブジェクトãŒç¯„囲内ã«å˜åœ¨ã—ãªã„ã‹ã€ã¾ãŸã¯å‰Šé™¤ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ </notification> <notification name="GestureSaveFailedReason"> 次ã®ç†ç”±ã§ã€ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã®ä¿å˜æ™‚ã«å•é¡ŒãŒèµ·ã“ã‚Šã¾ã—ãŸã€‚ [REASON]。 後ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。 </notification> <notification name="SaveNotecardFailObjectNotFound"> - ノートカードã®ä¿å˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚オブジェクトã€ã¾ãŸã¯é–¢é€£ã™ã‚‹ã‚ªãƒ–ジェクトæŒã¡ç‰©ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + ノートカードã®ä¿å˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚オブジェクトã€ã¾ãŸã¯é–¢é€£ã™ã‚‹ã‚ªãƒ–ジェクトインベントリãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 オブジェクトãŒç¯„囲内ã«å˜åœ¨ã—ãªã„ã‹ã€ã¾ãŸã¯å‰Šé™¤ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ </notification> <notification name="SaveNotecardFailReason"> @@ -514,11 +535,11 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã [REGION] ã§ã¯ã€åœ°å½¢ã®å¤‰æ›´ãŒã§ãã¾ã›ã‚“。 </notification> <notification name="CannotCopyWarning"> - ã‚ãªãŸã«ã¯[ITEMS]ã¨ã„ã†ã‚¢ã‚¤ãƒ†ãƒ をコピーã™ã‚‹è¨±å¯ãŒã‚ã‚Šã¾ã›ã‚“。他ã®ä½äººã«æä¾›ã™ã‚‹ã¨ã€ãã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã™ã€‚本当ã«ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’è²ã‚Šã¾ã™ã‹ï¼Ÿ + ã‚ãªãŸã«ã¯[ITEMS]ã¨ã„ã†ã‚¢ã‚¤ãƒ†ãƒ をコピーã™ã‚‹è¨±å¯ãŒã‚ã‚Šã¾ã›ã‚“。他ã®ä½äººã«æä¾›ã™ã‚‹ã¨ã€ãã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã™ã€‚本当ã«ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’è²ã‚Šã¾ã™ã‹ï¼Ÿ <usetemplate name="okcancelbuttons" notext="ã„ã„ãˆ" yestext="ã¯ã„"/> </notification> <notification name="CannotGiveItem"> - æŒã¡ç‰©ã®ã‚¢ã‚¤ãƒ†ãƒ を渡ã›ã¾ã›ã‚“。 + インベントリã®ã‚¢ã‚¤ãƒ†ãƒ を渡ã›ã¾ã›ã‚“。 </notification> <notification name="TransactionCancelled"> å–引ãŒã‚ャンセルã•ã‚Œã¾ã—ãŸã€‚ @@ -531,7 +552,7 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã </notification> <notification name="CannotCopyCountItems"> ã‚ãªãŸã¯é¸æŠžã—㟠[COUNT] 個ã®ã‚¢ã‚¤ãƒ†ãƒ ã®ã®ã‚³ãƒ”ーを許ã•ã‚Œã¦ã„ã¾ã›ã‚“。 -ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã‹ã‚‰å¤±ã‚ã‚Œã¾ã™ã€‚ +ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‹ã‚‰å¤±ã‚ã‚Œã¾ã™ã€‚ 本当ã«ã‚¢ã‚¤ãƒ†ãƒ を渡ã—ãŸã„ã§ã™ã‹ï¼Ÿ <usetemplate name="okcancelbuttons" notext="ã„ã„ãˆ" yestext="ã¯ã„"/> </notification> @@ -672,7 +693,7 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã 出力ファイルを作æˆã§ãã¾ã›ã‚“: [FILE] </notification> <notification name="DoNotSupportBulkAnimationUpload"> - ç¾åœ¨ [APP_NAME] ã§ã¯ã€ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®ä¸€æ‹¬ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。 + ç¾åœ¨ [APP_NAME] ã§ã¯ã€BVH å½¢å¼ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã®ä¸€æ‹¬ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。 </notification> <notification name="CannotUploadReason"> 次ã®ç†ç”±ã§ã€ã€Œ [FILE] ã€ã‚’アップãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“: [REASON] @@ -775,7 +796,7 @@ L$ ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã テレãƒãƒ¼ãƒˆç›®çš„地を見ã¤ã‘られã¾ã›ã‚“。目的地ãŒä¸€æ™‚çš„ã«åˆ©ç”¨ã§ããªã„状態ã‹ã€ã™ã§ã«æ¶ˆæ»…ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚数分後ã«ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。 </notification> <notification name="no_inventory_host"> - æŒã¡ç‰©ã‚·ã‚¹ãƒ†ãƒ ã¯ç¾åœ¨åˆ©ç”¨ã§ãã¾ã›ã‚“。 + インベントリシステムã¯ç¾åœ¨åˆ©ç”¨ã§ãã¾ã›ã‚“。 </notification> <notification name="CannotSetLandOwnerNothingSelected"> 土地所有者è¨å®šãŒã§ãã¾ã›ã‚“: @@ -938,7 +959,7 @@ L$ ã¯è¿”金ã•ã‚Œã¾ã›ã‚“。 <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/> </notification> <notification name="ConfirmItemCopy"> - ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ã‚ãªãŸã®æŒã¡ç‰©ã«ã‚³ãƒ”ーã—ã¾ã™ã‹ï¼Ÿ + ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ã‚³ãƒ”ーã—ã¾ã™ã‹ï¼Ÿ <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="コピー"/> </notification> <notification name="ResolutionSwitchFail"> @@ -990,7 +1011,7 @@ L$ ã¯è¿”金ã•ã‚Œã¾ã›ã‚“。 </form> </notification> <notification label="ç€ç”¨ç‰©ã‚’ä¿å˜" name="SaveWearableAs"> - アイテムを別åã§æŒã¡ç‰©ã«ä¿å˜ï¼š + アイテムを別åã§ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ä¿å˜ï¼š <form name="form"> <input name="message"> [DESC](新è¦ï¼‰ @@ -1472,8 +1493,8 @@ http://secondlife.com/download ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã <usetemplate ignoretext="オブジェクトを所有者ã«è¿”å´ã™ã‚‹å‰ã®ç¢ºèª" name="okcancelignore" notext="å–り消ã—" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - ç¾åœ¨ã‚ãªãŸã¯ <nolink>[GROUP]</nolink> ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã™ã€‚ -ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を抜ã‘ã¾ã™ã‹ï¼Ÿ + ç¾åœ¨ã€ã‚ãªãŸã¯ <nolink>[GROUP]</nolink> グループã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã™ã€‚ +グループã‹ã‚‰è„±é€€ã—ã¾ã™ã‹ï¼Ÿ <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/> </notification> <notification name="ConfirmKick"> @@ -1875,7 +1896,7 @@ Adult 専用リージョンã«å…¥ã‚‹ã«ã¯ã€ä½äººã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¹´é½¢ç¢ </notification> <notification name="BuyCopy"> コピーを [OWNER] ã‹ã‚‰ L$ [PRICE] ã§è³¼å…¥ã—ã¾ã™ã‹ï¼Ÿ -購入ã—ãŸã‚ªãƒ–ジェクトã¯ã€ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚ +購入ã—ãŸã‚ªãƒ–ジェクトã¯ã€ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚ å¯èƒ½ãªæ“作ã¯ã€ ä¿®æ£ï¼š[MODIFYPERM]ã€ã‚³ãƒ”ー:[COPYPERM]〠å†è²©ãƒ»ãƒ—レゼント:[RESELLPERM] ã§ã™ã€‚ @@ -1883,7 +1904,7 @@ Adult 専用リージョンã«å…¥ã‚‹ã«ã¯ã€ä½äººã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¹´é½¢ç¢ </notification> <notification name="BuyCopyNoOwner"> L$ [PRICE] ã§ã‚³ãƒ”ーを購入ã—ã¾ã™ã‹ï¼Ÿ -購入ã—ãŸã‚ªãƒ–ジェクトã¯ã€ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚ +購入ã—ãŸã‚ªãƒ–ジェクトã¯ã€ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚ å¯èƒ½ãªæ“作ã¯ã€ ä¿®æ£ï¼š[MODIFYPERM]ã€ã‚³ãƒ”ー:[COPYPERM]〠å†è²©ãƒ»ãƒ—レゼント:[RESELLPERM] ã§ã™ã€‚ @@ -1891,12 +1912,12 @@ Adult 専用リージョンã«å…¥ã‚‹ã«ã¯ã€ä½äººã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¹´é½¢ç¢ </notification> <notification name="BuyContents"> ä¸èº«ã‚’ [OWNER] ã‹ã‚‰ L$ [PRICE] ã§è³¼å…¥ã—ã¾ã™ã‹ï¼Ÿ -購入ã—ãŸä¸èº«ã¯ã€ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚ +購入ã—ãŸä¸èº«ã¯ã€ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚ <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/> </notification> <notification name="BuyContentsNoOwner"> L$ [PRICE] ã§ä¸èº«ã‚’購入ã—ã¾ã™ã‹ï¼Ÿ -購入ã—ãŸä¸èº«ã¯ã€ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚ +購入ã—ãŸä¸èº«ã¯ã€ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ã‚³ãƒ”ーã•ã‚Œã¾ã™ã€‚ <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/> </notification> <notification name="ConfirmPurchase"> @@ -1925,20 +1946,20 @@ Adult 専用リージョンã«å…¥ã‚‹ã«ã¯ã€ä½äººã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¹´é½¢ç¢ <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="MoveInventoryFromObject"> - 「コピーä¸å¯ã€ã®æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠžã—ã¾ã—ãŸã€‚ -ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚³ãƒ”ーã•ã‚Œãªã„ã¾ã¾ã€ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã«ç§»å‹•ã•ã‚Œã¾ã™ã€‚ + 「コピーä¸å¯ã€ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠžã—ã¾ã—ãŸã€‚ +ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚³ãƒ”ーã•ã‚Œãªã„ã¾ã¾ã€ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ç§»å‹•ã•ã‚Œã¾ã™ã€‚ アイテムを動ã‹ã—ã¾ã™ã‹ï¼Ÿ <usetemplate ignoretext="「コピーä¸å¯ã€ã®ã‚¢ã‚¤ãƒ†ãƒ をオブジェクトã‹ã‚‰å‹•ã‹ã™å‰ã®è¦å‘Š" name="okcancelignore" notext="ã‚ャンセル" yestext="OK"/> </notification> <notification name="MoveInventoryFromScriptedObject"> - 「コピーä¸å¯ã€ã®æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠžã—ã¾ã—ãŸã€‚ -ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚³ãƒ”ーã•ã‚Œãšã«ã€ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã«ç§»å‹•ã•ã‚Œã¾ã™ã€‚ -ã“ã®ã‚ªãƒ–ジェクトã¯ã‚¹ã‚¯ãƒªãƒ—ト付ããªã®ã§ã€ã€ŒæŒã¡ç‰©ã€ã«ç§»å‹•ã•ã›ã‚‹ã¨ + 「コピーä¸å¯ã€ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠžã—ã¾ã—ãŸã€‚ +ã“れらã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚³ãƒ”ーã•ã‚Œãšã«ã€ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ç§»å‹•ã•ã‚Œã¾ã™ã€‚ +ã“ã®ã‚ªãƒ–ジェクトã¯ã‚¹ã‚¯ãƒªãƒ—ト付ããªã®ã§ã€ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ç§»å‹•ã•ã›ã‚‹ã¨ スクリプトã«èª¤å‹•ä½œãŒèµ·ãã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ -æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ を移動ã—ã¾ã™ã‹ï¼Ÿ +インベントリアイテムを移動ã—ã¾ã™ã‹ï¼Ÿ <usetemplate ignoretext="スクリプト入りã®ã‚ªãƒ–ジェクトを壊ã™æã‚Œã®ã‚る「コピーä¸å¯ã€ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’å‹•ã‹ã™å‰ã®è¦å‘Š" name="okcancelignore" notext="ã‚ャンセル" yestext="OK"/> </notification> <notification name="ClickActionNotPayable"> @@ -2047,7 +2068,7 @@ Linden Lab </notification> <notification name="ConfirmEmptyTrash"> ã”ã¿ç®±ã®ä¸èº«ã‚’ã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ - <usetemplate ignoretext="æŒã¡ç‰©ã®ã”ã¿ç®±ãƒ•ã‚©ãƒ«ãƒ€ã‚’空ã«ã™ã‚‹å‰ã®ç¢ºèª" name="okcancelignore" notext="ã‚ャンセル" yestext="OK"/> + <usetemplate ignoretext="インベントリã®ã”ã¿ç®±ãƒ•ã‚©ãƒ«ãƒ€ã‚’空ã«ã™ã‚‹å‰ã®ç¢ºèª" name="okcancelignore" notext="ã‚ャンセル" yestext="OK"/> </notification> <notification name="ConfirmClearBrowserCache"> トラベルã€Webã€æ¤œç´¢ã®å±¥æ´ã‚’ã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ @@ -2231,7 +2252,7 @@ Web ページã«ãƒªãƒ³ã‚¯ã™ã‚‹ã¨ã€ä»–人ãŒã“ã®å ´æ‰€ã«ç°¡å˜ã«ã‚¢ã‚¯ã‚»ã 親エステート間ã§ã¯ IM ã‚’é€ä¿¡ã§ãã¾ã›ã‚“。 </notification> <notification name="TransferInventoryAcrossParentEstates"> - 親エステート間ã§æŒã¡ç‰©ã‚’移動ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 + 親エステート間ã§ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‚’移動ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 </notification> <notification name="UnableToLoadNotecard"> ノートカードをèªã¿è¾¼ã‚ã¾ã›ã‚“。ã‚ã¨ã§å†åº¦ãŠè©¦ã—ãã ã•ã„。 @@ -2283,7 +2304,7 @@ Web ページã«ãƒªãƒ³ã‚¯ã™ã‚‹ã¨ã€ä»–人ãŒã“ã®å ´æ‰€ã«ç°¡å˜ã«ã‚¢ã‚¯ã‚»ã [NAME] ã¯ã€ã‚ãªãŸãŒæ¸¡ã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’å—ã‘å–ã‚Šã¾ã—ãŸã€‚ </notification> <notification name="InventoryDeclined"> - [NAME] ã¯ã€æŒã¡ç‰©ã®æ供をæ–ã‚Šã¾ã—ãŸã€‚ + [NAME] ã¯ã€ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã®æ供をæ–ã‚Šã¾ã—ãŸã€‚ </notification> <notification name="ObjectMessage"> [NAME]: [MESSAGE] @@ -2368,16 +2389,16 @@ Web ページã«ãƒªãƒ³ã‚¯ã™ã‚‹ã¨ã€ä»–人ãŒã“ã®å ´æ‰€ã«ç°¡å˜ã«ã‚¢ã‚¯ã‚»ã </form> </notification> <notification name="OwnedObjectsReturned"> - é¸æŠžã—ãŸåœŸåœ°ã®åŒºç”»ä¸Šã«ã‚ã£ãŸã‚ãªãŸã®ã‚ªãƒ–ジェクトã¯ã€ã™ã¹ã¦ã‚ãªãŸã®ã€ŒæŒã¡ç‰©ã€ã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚ + é¸æŠžã—ãŸåœŸåœ°ã®åŒºç”»ä¸Šã«ã‚ã£ãŸã‚ãªãŸã®ã‚ªãƒ–ジェクトã¯ã€ã™ã¹ã¦ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚ </notification> <notification name="OtherObjectsReturned"> - [NAME] ãŒæ‰€æœ‰ã™ã‚‹ã€é¸æŠžã—ãŸåŒºç”»ã«ã‚るオブジェクトã¯ã€æ‰€æœ‰è€…ã®æŒã¡ç‰©ã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚ + [NAME] ãŒæ‰€æœ‰ã™ã‚‹ã€é¸æŠžã—ãŸåŒºç”»ã«ã‚るオブジェクトã¯ã€æ‰€æœ‰è€…ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚ </notification> <notification name="OtherObjectsReturned2"> 「 [NAME] ã€ã¨ã„ã†åå‰ã®ä½äººãŒæ‰€æœ‰ã™ã‚‹ã€é¸æŠžã—ãŸåŒºç”»ä¸Šã®ã‚ªãƒ–ジェクトã¯ã€æœ¬äººã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚ </notification> <notification name="GroupObjectsReturned"> - é¸æŠžã—ãŸåŒºç”»ä¸Šã®ã€[GROUPNAME] ã¨ã„ã†ã‚°ãƒ«ãƒ¼ãƒ—ã¨å…±æœ‰ã—ã¦ã„ãŸã‚ªãƒ–ジェクトã¯ã€ãã‚Œãžã‚Œã®æ‰€æœ‰è€…ã®ã€ŒæŒã¡ç‰©ã€ã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚ + é¸æŠžã—ãŸåŒºç”»ä¸Šã®ã€[GROUPNAME] ã¨ã„ã†ã‚°ãƒ«ãƒ¼ãƒ—ã¨å…±æœ‰ã—ã¦ã„ãŸã‚ªãƒ–ジェクトã¯ã€ãã‚Œãžã‚Œã®æ‰€æœ‰è€…ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚ è²æ¸¡ã•ã‚Œã¦ã„ãŸã€Œå†è²©ãƒ»ãƒ—レゼントå¯ã€ã®ã‚ªãƒ–ジェクトã¯ã€ä»¥å‰ã®æ‰€æœ‰è€…ã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚ グループã«è²æ¸¡ã•ã‚Œã¦ã„ãŸã€Œå†è²©ãƒ»ãƒ—レゼントä¸å¯ã€ã®ã‚ªãƒ–ジェクトã¯ã€å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚ </notification> @@ -2596,7 +2617,7 @@ Web ページã«ãƒªãƒ³ã‚¯ã™ã‚‹ã¨ã€ä»–人ãŒã“ã®å ´æ‰€ã«ç°¡å˜ã«ã‚¢ã‚¯ã‚»ã </notification> <notification name="OfferCallingCard"> [NAME] ãŒã‚³ãƒ¼ãƒªãƒ³ã‚°ã‚«ãƒ¼ãƒ‰ã‚’渡ãã†ã¨ã—ã¦ã„ã¾ã™ã€‚ -ã‚ãªãŸã®æŒã¡ç‰©ã«ãƒ–ックマークãŒè¿½åŠ ã•ã‚Œã€ã“ã®ä½äººã«ç´ æ—©ã IM ã‚’é€ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ +ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ãƒ–ックマークãŒè¿½åŠ ã•ã‚Œã€ã“ã®ä½äººã«ç´ æ—©ã IM ã‚’é€ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ <form name="form"> <button name="Accept" text="å—ã‘入れる"/> <button name="Decline" text="辞退"/> @@ -2658,16 +2679,16 @@ Web ページã«ãƒªãƒ³ã‚¯ã™ã‚‹ã¨ã€ä»–人ãŒã“ã®å ´æ‰€ã«ç°¡å˜ã«ã‚¢ã‚¯ã‚»ã [NAME] ã®ã€Œ<nolink>[TITLE]</nolink>〠[MESSAGE] <form name="form"> - <button name="Mute" text="ブãƒãƒƒã‚¯"/> - <button name="Ignore" text="無視ã™ã‚‹"/> + <button name="Client_Side_Mute" text="ブãƒãƒƒã‚¯"/> + <button name="Client_Side_Ignore" text="無視"/> </form> </notification> <notification name="ScriptDialogGroup"> [GROUPNAME] ã®ã€Œ<nolink>[TITLE]</nolink>〠[MESSAGE] <form name="form"> - <button name="Mute" text="ブãƒãƒƒã‚¯"/> - <button name="Ignore" text="無視ã™ã‚‹"/> + <button name="Client_Side_Mute" text="ブãƒãƒƒã‚¯"/> + <button name="Client_Side_Ignore" text="無視"/> </form> </notification> <notification name="BuyLindenDollarSuccess"> @@ -2686,7 +2707,7 @@ M ã‚ーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚ <notification name="FirstSandbox"> ã“ã“ã¯ã‚µãƒ³ãƒ‰ãƒœãƒƒã‚¯ã‚¹ã‚¨ãƒªã‚¢ã§ã™ã€‚ä½äººãŒåˆ¶ä½œã‚’å¦ã¶ã“ã¨ãŒã§ãã¾ã™ã€‚ -ã“ã“ã§åˆ¶ä½œã•ã‚ŒãŸã‚‚ã®ã¯æ™‚é–“ãŒçµŒã¤ã¨å‰Šé™¤ã•ã‚Œã¾ã™ã€‚制作ã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’å³ã‚¯ãƒªãƒƒã‚¯ã—ã¦ã€Œå–ã‚‹ã€ã‚’é¸ã³ã€æŒã¡ç‰©ã«å…¥ã‚Œã¦ãŠæŒã¡å¸°ã‚Šã™ã‚‹ã®ã‚’ãŠå¿˜ã‚Œãªã。 +ã“ã“ã§åˆ¶ä½œã•ã‚ŒãŸã‚‚ã®ã¯æ™‚é–“ãŒçµŒã¤ã¨å‰Šé™¤ã•ã‚Œã¾ã™ã€‚制作ã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’å³ã‚¯ãƒªãƒƒã‚¯ã—ã¦ã€Œå–ã‚‹ã€ã‚’é¸ã³ã€ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«å…¥ã‚Œã¦ãŠæŒã¡å¸°ã‚Šã™ã‚‹ã®ã‚’ãŠå¿˜ã‚Œãªã。 </notification> <notification name="MaxListSelectMessage"> ã“ã®ãƒªã‚¹ãƒˆã‹ã‚‰ [MAX_SELECT] 個ã¾ã§ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠžã§ãã¾ã™ã€‚ @@ -2707,7 +2728,7 @@ M ã‚ーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚ [NAME] ã¯ãŠé‡‘ã‚’å—ã‘å–ã‚Šã€è‡ªå‹•çš„ã«ãƒ–ãƒãƒƒã‚¯ãŒè§£é™¤ã•ã‚Œã¾ã—ãŸã€‚ </notification> <notification name="AutoUnmuteByInventory"> - [NAME] ã¯æŒã¡ç‰©ã‚’å—ã‘å–ã‚Šã€è‡ªå‹•çš„ã«ãƒ–ãƒãƒƒã‚¯ãŒè§£é™¤ã•ã‚Œã¾ã—ãŸã€‚ + [NAME] ã¯ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‚’å—ã‘å–ã‚Šã€è‡ªå‹•çš„ã«ãƒ–ãƒãƒƒã‚¯ãŒè§£é™¤ã•ã‚Œã¾ã—ãŸã€‚ </notification> <notification name="VoiceInviteGroup"> [NAME] 㯠[GROUP] ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã‚³ãƒ¼ãƒ«ã«å‚åŠ ã—ã¾ã—ãŸã€‚ @@ -2862,6 +2883,30 @@ M ã‚ーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚ [RESIDENTS] <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/> </notification> + <notification name="ShareFolderConfirmation"> + フォルダã¯ä¸€åº¦ã« 1 ã¤ã—ã‹å…±æœ‰ã§ãã¾ã›ã‚“。 + +次ã®ã‚¢ã‚¤ãƒ†ãƒ を共有ã—ã¾ã™ã‹ï¼Ÿ + +<nolink>[ITEMS]</nolink> + +次ã®ä½äººã¨å…±æœ‰ï¼š + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="Ok"/> + </notification> + <notification name="ShareFolderConfirmation"> + フォルダã¯ä¸€åº¦ã« 1 ã¤ã—ã‹å…±æœ‰ã§ãã¾ã›ã‚“。 + +次ã®ã‚¢ã‚¤ãƒ†ãƒ を共有ã—ã¾ã™ã‹ï¼Ÿ + +<nolink>[ITEMS]</nolink> + +次ã®ä½äººã¨å…±æœ‰ï¼š + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="Ok"/> + </notification> <notification name="ItemsShared"> アイテムãŒå…±æœ‰ã•ã‚Œã¾ã—ãŸã€‚ </notification> @@ -2988,7 +3033,7 @@ M ã‚ーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚ カメラã®è¦–点を変更ã™ã‚‹ã«ã¯ã€æ°´å¹³ãƒ»åž‚直コントãƒãƒ¼ãƒ«ã‚’使ã„ã¾ã™ã€‚Escape を押ã™ã‹ã€ã¾ãŸã¯æ©è¡Œã™ã‚‹ã¨ã€è¦–点ãŒãƒªã‚»ãƒƒãƒˆã•ã‚Œã¾ã™ã€‚ </notification> <notification label="インベントリ" name="HintInventory"> - æŒã¡ç‰©ã«ã¯ã‚ãªãŸã®ã‚¢ã‚¤ãƒ†ãƒ ãŒã™ã¹ã¦å«ã¾ã‚Œã¾ã™ã€‚æ–°ã—ãè¿½åŠ ã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã¯ã€Œæœ€æ–°ã€ã‚¿ãƒ–ã«ä¸€è¦§è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚ + インベントリã«ã¯ã‚ãªãŸã®ã‚¢ã‚¤ãƒ†ãƒ ãŒã™ã¹ã¦å«ã¾ã‚Œã¾ã™ã€‚æ–°ã—ãè¿½åŠ ã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ ã¯ã€Œæœ€æ–°ã€ã‚¿ãƒ–ã«ä¸€è¦§è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚ </notification> <notification label="ã‚ãªãŸã®ãƒªãƒ³ãƒ‡ãƒ³ãƒ‰ãƒ«" name="HintLindenDollar"> ã“ã‚ŒãŒã‚ãªãŸã® L$ 残高ã§ã™ã€‚リンデンドルを購入ã™ã‚‹ã«ã¯ã€ŒL$ ã®è³¼å…¥ã€ã‚’クリックã—ã¾ã™ã€‚ @@ -3096,7 +3141,7 @@ M ã‚ーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚ <usetemplate name="okcancelbuttons" notext="終了ã—ãªã„" yestext="終了"/> </notification> <notification label="" name="NoInventory"> - æŒã¡ç‰©ã®è¡¨ç¤ºã¯ã‚¢ãƒ‰ãƒãƒ³ã‚¹ãƒ¢ãƒ¼ãƒ‰ã§ã®ã¿åˆ©ç”¨ã§ãã¾ã™ã€‚ãƒã‚°ã‚¢ã‚¦ãƒˆã—ã¦ãƒ¢ãƒ¼ãƒ‰ã‚’変更ã—ã¾ã™ã‹ï¼Ÿ + インベントリã®è¡¨ç¤ºã¯ã‚¢ãƒ‰ãƒãƒ³ã‚¹ãƒ¢ãƒ¼ãƒ‰ã§ã®ã¿åˆ©ç”¨ã§ãã¾ã™ã€‚ãƒã‚°ã‚¢ã‚¦ãƒˆã—ã¦ãƒ¢ãƒ¼ãƒ‰ã‚’変更ã—ã¾ã™ã‹ï¼Ÿ <usetemplate name="okcancelbuttons" notext="終了ã—ãªã„" yestext="終了"/> </notification> <notification label="" name="NoAppearance"> diff --git a/indra/newview/skins/default/xui/ja/panel_group_control_panel.xml b/indra/newview/skins/default/xui/ja/panel_group_control_panel.xml index f7f575206a..49749732c9 100644 --- a/indra/newview/skins/default/xui/ja/panel_group_control_panel.xml +++ b/indra/newview/skins/default/xui/ja/panel_group_control_panel.xml @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="panel_im_control_panel"> <layout_stack name="vertical_stack"> <layout_panel name="group_info_btn_panel"> - <button label="ã‚°ãƒ«ãƒ¼ãƒ—æƒ…å ±" name="group_info_btn"/> + <button label="グループプãƒãƒ•ã‚£ãƒ¼ãƒ«" name="group_info_btn"/> </layout_panel> <layout_panel name="call_btn_panel"> <button label="グループコール" name="call_btn"/> diff --git a/indra/newview/skins/default/xui/ja/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/ja/panel_group_info_sidetray.xml index 85406702bc..7aa1aec6d0 100644 --- a/indra/newview/skins/default/xui/ja/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/ja/panel_group_info_sidetray.xml @@ -1,5 +1,5 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="ã‚°ãƒ«ãƒ¼ãƒ—æƒ…å ±" name="GroupInfo"> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="グループインベントリ" name="GroupInfo"> <panel.string name="default_needs_apply_text"> ä¿å˜ã—ã¦ã„ãªã„変更ãŒã‚ã‚Šã¾ã™ </panel.string> diff --git a/indra/newview/skins/default/xui/ja/panel_group_notices.xml b/indra/newview/skins/default/xui/ja/panel_group_notices.xml index 96e0382975..ddad6c1f9b 100644 --- a/indra/newview/skins/default/xui/ja/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/ja/panel_group_notices.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="通知" name="notices_tab"> <panel.string name="help_text"> 通知ã§ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ã‚‹ã“ã¨ãŒã§ãã€é€šçŸ¥ã«ã‚¢ã‚¤ãƒ†ãƒ を添付ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ @@ -39,10 +39,10 @@ <text name="string"> ã“ã“ã«ã‚¢ã‚¤ãƒ†ãƒ をドラッグ&ドãƒãƒƒãƒ—ã—ã¦æ·»ä»˜ã—ã¦ãã ã•ã„: </text> - <button label="æŒã¡ç‰©" name="open_inventory" tool_tip="æŒã¡ç‰©ã‚’é–‹ãã¾ã™"/> + <button label="インベントリ" name="open_inventory" tool_tip="インベントリを開ãã¾ã™"/> <button label="å–り外ã™" label_selected="添付物を削除" name="remove_attachment" tool_tip="ã‚ãªãŸã®é€šçŸ¥ã‹ã‚‰æ·»ä»˜ã•ã‚ŒãŸã‚¢ã‚¤ãƒ†ãƒ を削除ã—ã¾ã™"/> <button label="é€ä¿¡" label_selected="é€ä¿¡" name="send_notice"/> - <group_drop_target name="drop_target" tool_tip="æŒã¡ç‰©ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ã“ã®ãƒœãƒƒã‚¯ã‚¹ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ã€é€šçŸ¥ã¨ä¸€ç·’ã«é€ã‚Šã¾ã™ã€‚ 添付ã™ã‚‹ã«ã¯ã€ãã®ã‚¢ã‚¤ãƒ†ãƒ ã®ã‚³ãƒ”ーã¨å†è²©ãƒ»ãƒ—レゼントã®æ¨©é™ãŒã‚ãªãŸã«ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"/> + <group_drop_target name="drop_target" tool_tip="インベントリã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ã“ã®ãƒœãƒƒã‚¯ã‚¹ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ã€é€šçŸ¥ã¨ä¸€ç·’ã«é€ã‚Šã¾ã™ã€‚ 添付ã™ã‚‹ã«ã¯ã€ãã®ã‚¢ã‚¤ãƒ†ãƒ ã®ã‚³ãƒ”ーã¨å†è²©ãƒ»ãƒ—レゼントã®æ¨©é™ãŒã‚ãªãŸã«ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"/> </panel> <panel label="éŽåŽ»ã®é€šçŸ¥ã‚’表示" name="panel_view_past_notice"> <text name="lbl"> diff --git a/indra/newview/skins/default/xui/ja/panel_landmarks.xml b/indra/newview/skins/default/xui/ja/panel_landmarks.xml index e3b716c35b..24d6ff23ae 100644 --- a/indra/newview/skins/default/xui/ja/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/ja/panel_landmarks.xml @@ -1,9 +1,9 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="Landmarks"> <accordion name="landmarks_accordion"> <accordion_tab name="tab_favorites" title="ãŠæ°—ã«å…¥ã‚Šãƒãƒ¼"/> <accordion_tab name="tab_landmarks" title="マイ ランドマーク"/> - <accordion_tab name="tab_inventory" title="æŒã¡ç‰©"/> + <accordion_tab name="tab_inventory" title="インベントリ"/> <accordion_tab name="tab_library" title="ライブラリ"/> </accordion> <panel name="bottom_panel"> diff --git a/indra/newview/skins/default/xui/ja/panel_main_inventory.xml b/indra/newview/skins/default/xui/ja/panel_main_inventory.xml index ff968696b7..f908262f4f 100644 --- a/indra/newview/skins/default/xui/ja/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/ja/panel_main_inventory.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="ã‚‚ã®" name="main inventory panel"> <panel.string name="ItemcountFetching"> [ITEM_COUNT] 個ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’å–å¾—ä¸ã§ã™... [FILTER] @@ -9,9 +9,9 @@ <text name="ItemcountText"> アイテム: </text> - <filter_editor label="æŒã¡ç‰©ã‚’フィルター" name="inventory search editor"/> + <filter_editor label="インベントリをフィルター" name="inventory search editor"/> <tab_container name="inventory filter tabs"> - <inventory_panel label="æŒã¡ç‰©" name="All Items"/> + <inventory_panel label="インベントリ" name="All Items"/> <recent_inventory_panel label="最新" name="Recent Items"/> </tab_container> <layout_stack name="bottom_panel"> diff --git a/indra/newview/skins/default/xui/ja/panel_me.xml b/indra/newview/skins/default/xui/ja/panel_me.xml index 896bbff0ee..3df1ae8048 100644 --- a/indra/newview/skins/default/xui/ja/panel_me.xml +++ b/indra/newview/skins/default/xui/ja/panel_me.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="マイ プãƒãƒ•ã‚£ãƒ¼ãƒ«" name="panel_me"> - <panel label="マイ ピック" name="panel_picks"/> + <panel label="マイ-ピック" name="panel_picks"/> </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_nearby_chat.xml b/indra/newview/skins/default/xui/ja/panel_nearby_chat.xml index aca055bb43..4048b48d3a 100644 --- a/indra/newview/skins/default/xui/ja/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/ja/panel_nearby_chat.xml @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="nearby_chat"> - <check_box label="ãƒãƒ£ãƒƒãƒˆã‚’翻訳" name="translate_chat_checkbox"/> + <layout_stack name="stack"> + <layout_panel name="translate_chat_checkbox_lp"> + <check_box label="ãƒãƒ£ãƒƒãƒˆã‚’翻訳" name="translate_chat_checkbox"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/ja/panel_outbox_inventory.xml index 47f570ab86..1a14283113 100644 --- a/indra/newview/skins/default/xui/ja/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/ja/panel_outbox_inventory.xml @@ -1,2 +1,2 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<outbox_inventory_panel name="inventory_outbox" tool_tip="商å“ã‚’ã“ã“ã«ãƒ‰ãƒ©ãƒƒã‚°ã‚¢ãƒ³ãƒ‰ãƒ‰ãƒãƒƒãƒ—ã™ã‚‹ã¨ã€ã‚ãªãŸã®åº—é ã«ä¸¦ã³ã¾ã™"/> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<outbox_inventory_panel name="inventory_outbox" tool_tip="アイテムをã“ã“ã«ãƒ‰ãƒ©ãƒƒã‚°ã‚¢ãƒ³ãƒ‰ãƒ‰ãƒãƒƒãƒ—ã™ã‚‹ã¨ã€ã‚ãªãŸã®åº—é ã«ä¸¦ã³ã¾ã™"/> diff --git a/indra/newview/skins/default/xui/ja/panel_outfit_edit.xml b/indra/newview/skins/default/xui/ja/panel_outfit_edit.xml index 6897660214..e89ce0c479 100644 --- a/indra/newview/skins/default/xui/ja/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/ja/panel_outfit_edit.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <!-- Side tray Outfit Edit panel --> <panel label="アウトフットã®ç·¨é›†" name="outfit_edit"> <string name="No Outfit" value="アウトフィットãªã—"/> @@ -30,7 +30,7 @@ <button label="ã•ã‚‰ã«è¿½åŠ ..." name="show_add_wearables_btn" tool_tip="é–‹ãï¼é–‰ã˜ã‚‹"/> </layout_panel> <layout_panel name="filter_panel"> - <filter_editor label="æŒã¡ç‰©ã®ç€ç”¨ç‰©ã‚’フィルター" name="look_item_filter"/> + <filter_editor label="インベントリã®ç€ç”¨ç‰©ã‚’フィルター" name="look_item_filter"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/ja/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/ja/panel_outfits_inventory.xml index 2a0647653d..93df0ba2bd 100644 --- a/indra/newview/skins/default/xui/ja/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/ja/panel_outfits_inventory.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="ã‚‚ã®" name="Outfits"> <panel.string name="wear_outfit_tooltip"> é¸æŠžã—ãŸã‚¢ã‚¦ãƒˆãƒ•ã‚£ãƒƒãƒˆã‚’ç€ç”¨ã™ã‚‹ </panel.string> <panel.string name="wear_items_tooltip"> - é¸æŠžã—ãŸå•†å“ã‚’ç€ç”¨ + é¸æŠžã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’ç€ç”¨ </panel.string> <tab_container name="appearance_tabs"> <panel label="マイ アウトフィット" name="outfitslist_tab"/> diff --git a/indra/newview/skins/default/xui/ja/panel_people.xml b/indra/newview/skins/default/xui/ja/panel_people.xml index 1c90f7327e..88c31451b5 100644 --- a/indra/newview/skins/default/xui/ja/panel_people.xml +++ b/indra/newview/skins/default/xui/ja/panel_people.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <!-- Side tray panel --> <panel label="人" name="people_panel"> <string name="no_recent_people" value="最近交æµã—ãŸäººã¯ã„ã¾ã›ã‚“。 一緒ã«ä½•ã‹ã™ã‚‹ä»²é–“ã‚’ãŠæŽ¢ã—ã§ã™ã‹ï¼Ÿ [secondlife:///app/search/people 検索] ã‹ [secondlife:///app/worldmap 世界地図] ã‚’ãŠè©¦ã—ãã ã•ã„。"/> @@ -73,7 +73,7 @@ <button label="コール" name="call_btn" tool_tip="ã“ã®ä½äººã«ã‚³ãƒ¼ãƒ«ã™ã‚‹"/> </layout_panel> <layout_panel name="share_btn_lp"> - <button label="共有" name="share_btn" tool_tip="「æŒã¡ç‰©ã€ã®ã‚¢ã‚¤ãƒ†ãƒ を共有ã™ã‚‹"/> + <button label="共有" name="share_btn" tool_tip="インベントリã®ã‚¢ã‚¤ãƒ†ãƒ を共有ã™ã‚‹"/> </layout_panel> <layout_panel name="teleport_btn_lp"> <button label="テレãƒãƒ¼ãƒˆ" name="teleport_btn" tool_tip="テレãƒãƒ¼ãƒˆã‚’é€ã‚Šã¾ã™"/> @@ -81,7 +81,7 @@ </layout_stack> <layout_stack name="bottom_bar_ls1"> <layout_panel name="group_info_btn_lp"> - <button label="ã‚°ãƒ«ãƒ¼ãƒ—æƒ…å ±" name="group_info_btn" tool_tip="ã‚°ãƒ«ãƒ¼ãƒ—æƒ…å ±ã‚’è¡¨ç¤ºã—ã¾ã™"/> + <button label="グループプãƒãƒ•ã‚£ãƒ¼ãƒ«" name="group_info_btn" tool_tip="グループプãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’表示ã—ã¾ã™"/> </layout_panel> <layout_panel name="chat_btn_lp"> <button label="グループãƒãƒ£ãƒƒãƒˆ" name="chat_btn" tool_tip="ãƒãƒ£ãƒƒãƒˆã‚’開始ã—ã¾ã™"/> diff --git a/indra/newview/skins/default/xui/ja/panel_region_estate.xml b/indra/newview/skins/default/xui/ja/panel_region_estate.xml index 5b2ef36045..2e58c5a8f1 100644 --- a/indra/newview/skins/default/xui/ja/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/ja/panel_region_estate.xml @@ -16,10 +16,10 @@ (ä¸æ˜Žï¼‰ </text> <text name="Only Allow"> - 次ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ã¿ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ï¼š + 次ã®ä½äººã«ã®ã¿ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ï¼š </text> - <check_box label="æ”¯æ‰•æƒ…å ±ç™»éŒ²æ¸ˆ" name="limit_payment" tool_tip="未確èªã®ä½äººã®ç«‹å…¥ã‚’ç¦æ¢ã—ã¾ã™"/> - <check_box label="年齢確èªæ¸ˆ" name="limit_age_verified" tool_tip="年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„ä½äººã®ç«‹å…¥ã‚’ç¦æ¢ã—ã¾ã™ã€‚ 詳ã—ã„æƒ…å ±ã¯ [SUPPORT_SITE] ã‚’ã”覧下ã•ã„。"/> + <check_box label="æ”¯æ‰•æƒ…æƒ…å ±ãŒç™»éŒ²ã•ã‚Œã¦ã„ã‚‹" name="limit_payment" tool_tip="æ”¯æ‰•æƒ…å ±ãŒç™»éŒ²ã•ã‚Œã¦ã„ãªã„ã¨ã€ã“ã®ä¸å‹•ç”£ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。詳細ã«ã¤ã„ã¦ã¯ã€[SUPPORT_SITE] ã‚’ã”覧ãã ã•ã„。"/> + <check_box label="年齢確èªãŒæ¸ˆã‚“ã§ã„ã‚‹" name="limit_age_verified" tool_tip="ã“ã®ä¸å‹•ç”£ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ã€å¹´é½¢ç¢ºèªã‚’済ã¾ã›ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚詳細ã«ã¤ã„ã¦ã¯ã€[SUPPORT_SITE] ã‚’ã”覧ãã ã•ã„。"/> <check_box label="ボイスãƒãƒ£ãƒƒãƒˆã‚’許å¯" name="voice_chat_check"/> <button label="?" name="voice_chat_help"/> <text name="abuse_email_text"> diff --git a/indra/newview/skins/default/xui/ja/panel_script_ed.xml b/indra/newview/skins/default/xui/ja/panel_script_ed.xml index 9fdd16d567..14d55002a3 100644 --- a/indra/newview/skins/default/xui/ja/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/ja/panel_script_ed.xml @@ -22,6 +22,8 @@ <menu label="ファイル" name="File"> <menu_item_call label="ä¿å˜" name="Save"/> <menu_item_call label="変更を元ã«æˆ»ã™" name="Revert All Changes"/> + <menu_item_call label="ファイルã‹ã‚‰ãƒãƒ¼ãƒ‰..." name="LoadFromFile"/> + <menu_item_call label="ファイルã«ä¿å˜..." name="SaveToFile"/> </menu> <menu label="編集" name="Edit"> <menu_item_call label="å…ƒã«æˆ»ã™" name="Undo"/> diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml index 46f2b0a3f9..e496e6602b 100644 --- a/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="panel_snapshot_inventory"> <text name="title"> - 「æŒã¡ç‰©ã€ã«ä¿å˜ + インベントリã«ä¿å˜ </text> <text name="hint_lbl"> - ç”»åƒã‚’æŒã¡ç‰©ã«ä¿å˜ã™ã‚‹ã«ã¯ L$[UPLOAD_COST] ã®è²»ç”¨ãŒã‹ã‹ã‚Šã¾ã™ã€‚ç”»åƒã‚’テクスãƒãƒ£ã¨ã—ã¦ä¿å˜ã™ã‚‹ã«ã¯å¹³æ–¹å½¢å¼ã® 1 ã¤ã‚’é¸æŠžã—ã¦ãã ã•ã„。 + ç”»åƒã‚’インベントリã«ä¿å˜ã™ã‚‹ã«ã¯ L$[UPLOAD_COST] ã®è²»ç”¨ãŒã‹ã‹ã‚Šã¾ã™ã€‚ç”»åƒã‚’テクスãƒãƒ£ã¨ã—ã¦ä¿å˜ã™ã‚‹ã«ã¯å¹³æ–¹å½¢å¼ã® 1 ã¤ã‚’é¸æŠžã—ã¦ãã ã•ã„。 </text> <combo_box label="解åƒåº¦" name="texture_size_combo"> <combo_box.item label="ç¾åœ¨ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦" name="CurrentWindow"/> diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml index cd5b7590ad..c3b1cd91e7 100644 --- a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml +++ b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="panel_snapshot_options"> <button label="プãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒ•ã‚£ãƒ¼ãƒ‰ã«æŠ•ç¨¿ã™ã‚‹" name="save_to_profile_btn"/> <button label="メール" name="save_to_email_btn"/> - <button label="æŒã¡ç‰©ã«ä¿å˜ï¼ˆL$[Amount])" name="save_to_inventory_btn"/> + <button label="インベントリã«ä¿å˜ï¼ˆL$[Amount])" name="save_to_inventory_btn"/> <button label="コンピューターã«ä¿å˜" name="save_to_computer_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml index 4fb876f690..f09643d562 100644 --- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml @@ -15,7 +15,7 @@ <panel.string name="buycurrencylabel"> L$ [AMT] </panel.string> - <panel name="balance_bg"> + <panel left="-370" name="balance_bg" width="160"> <text name="balance" tool_tip="クリックã—㦠L$ 残高を更新" value="L$20"/> <button label="L$ ã®è³¼å…¥" name="buyL" tool_tip="クリックã—㦠L$ を購入ã—ã¾ã™"/> <button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開ã" width="40"/> diff --git a/indra/newview/skins/default/xui/ja/role_actions.xml b/indra/newview/skins/default/xui/ja/role_actions.xml index c53ad838f7..896ed556ae 100644 --- a/indra/newview/skins/default/xui/ja/role_actions.xml +++ b/indra/newview/skins/default/xui/ja/role_actions.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <role_actions> <action_set description="ã“れらã®èƒ½åŠ›ã«ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—メンãƒãƒ¼ã‚’è¿½åŠ ã€æŽ’除ã—ã€æ‹›å¾…状ãªã—ã«æ–°ãƒ¡ãƒ³ãƒãƒ¼ã®å‚åŠ ã‚’èªã‚る権é™ãŒå«ã¾ã‚Œã¾ã™ã€‚" name="Membership"> <action description="ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«äººã‚’招待" longdescription="「役割ã€ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã®ã€Œãƒ¡ãƒ³ãƒãƒ¼ã€ã‚¿ãƒ–内ã«ã‚る「招待ã€ãƒœã‚¿ãƒ³ã‚’押ã—ã¦ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ãƒ¡ãƒ³ãƒãƒ¼ã‚’招待ã—ã¾ã™ã€‚" name="member invite" value="1"/> @@ -51,7 +51,7 @@ <action description="グループ所有オブジェクトã®è¿”å´" longdescription="グループ所有ã®åŒºç”»ä¸Šã®ã‚ªãƒ–ジェクトã®ã†ã¡ã€ã‚°ãƒ«ãƒ¼ãƒ—所有ã®ã‚ªãƒ–ジェクトを返å´ã™ã‚‹ã«ã¯ã€ã€ŒåœŸåœ°æƒ…å ±ã€ï¼žã€Œã‚ªãƒ–ジェクトã€ã‚¿ãƒ–を使ã„ã¾ã™ã€‚" name="land return group owned" value="48"/> <action description="グループã«è¨å®šã•ã‚Œã¦ã„るオブジェクトを返å´" longdescription="グループ所有ã®åŒºç”»ä¸Šã®ã‚ªãƒ–ジェクトã®ã†ã¡ã€ã‚°ãƒ«ãƒ¼ãƒ—ã«è¨å®šã•ã‚Œã¦ã„るオブジェクトを返å´ã™ã‚‹ã«ã¯ã€ã€ŒåœŸåœ°æƒ…å ±ã€ï¼žã€Œã‚ªãƒ–ジェクトã€ã‚¿ãƒ–を使ã„ã¾ã™ã€‚" name="land return group set" value="33"/> <action description="éžã‚°ãƒ«ãƒ¼ãƒ—オブジェクトã®è¿”å´" longdescription="グループ所有ã®åŒºç”»ä¸Šã®ã‚ªãƒ–ジェクトã®ã†ã¡ã€ã‚°ãƒ«ãƒ¼ãƒ—以外ã®ã‚ªãƒ–ジェクトを返å´ã™ã‚‹ã«ã¯ã€ã€ŒåœŸåœ°æƒ…å ±ã€ï¼žã€Œã‚ªãƒ–ジェクトã€ã‚¿ãƒ–を使ã„ã¾ã™ã€‚" name="land return non group" value="34"/> - <action description="リンデン製ã®æ¤ç‰©ã‚’使用ã—ã¦æ™¯è¦³ä½œæˆ" longdescription="リンデン製ã®æ¨¹æœ¨ã€æ¤ç‰©ã€è‰ã‚’æ¤ãˆã‚‹ã€æ™¯è¦³ã¥ãã‚Šã®èƒ½åŠ›ã§ã™ã€‚ ã“れらã®æ¤ç‰©ã¯ã‚ãªãŸã®æŒã¡ç‰©å†…ã®ã€Œãƒ©ã‚¤ãƒ–ラリ〠> 「オブジェクトã€ãƒ•ã‚©ãƒ«ãƒ€ã«ã‚ã‚Šã¾ã™ã€‚「制作ã€ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã§ä½œæˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚" name="land gardening" value="35"/> + <action description="リンデン製ã®æ¤ç‰©ã‚’使用ã—ã¦æ™¯è¦³ä½œæˆ" longdescription="リンデン製ã®æ¨¹æœ¨ã€æ¤ç‰©ã€è‰ã‚’æ¤ãˆã‚‹ã€æ™¯è¦³ã¥ãã‚Šã®èƒ½åŠ›ã§ã™ã€‚ ã“れらã®æ¤ç‰©ã¯ã‚ãªãŸã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªå†…ã®ã€Œãƒ©ã‚¤ãƒ–ラリ〠> 「オブジェクトã€ãƒ•ã‚©ãƒ«ãƒ€ã«ã‚ã‚Šã¾ã™ã€‚「制作ã€ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã§ä½œæˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚" name="land gardening" value="35"/> </action_set> <action_set description="ã“れらã®ã€Œèƒ½åŠ›ã€ã«ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—所有ã®ã‚ªãƒ–ジェクトをè²æ¸¡ã€ä¿®æ£ã€è²©å£²ã™ã‚‹æ¨©é™ãŒå«ã¾ã‚Œã¾ã™ã€‚ 変更ã¯ã€Œåˆ¶ä½œãƒ„ール〠> 「一般ã€ã‚¿ãƒ–ã§è¡Œã„ã¾ã™ã€‚ オブジェクトをå³ã‚¯ãƒªãƒƒã‚¯ã—ã¦ã€Œç·¨é›†ã€ã‚’é–‹ãã¨è¨å®šå†…容を確èªã§ãã¾ã™ã€‚" name="Object Management"> <action description="グループã«ã‚ªãƒ–ジェクトをè²æ¸¡" longdescription="「制作ツール〠> 「一般ã€ã‚¿ãƒ–ã§ã€ã‚ªãƒ–ジェクトをグループã«è²æ¸¡ã—ã¾ã™ã€‚" name="object deed" value="36"/> diff --git a/indra/newview/skins/default/xui/ja/sidepanel_inventory.xml b/indra/newview/skins/default/xui/ja/sidepanel_inventory.xml index fc0293307b..51d6d48f90 100644 --- a/indra/newview/skins/default/xui/ja/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/ja/sidepanel_inventory.xml @@ -2,47 +2,24 @@ <panel label="ã‚‚ã®" name="objects panel"> <panel label="" name="sidepanel__inventory_panel"> <layout_stack name="inventory_layout_stack"> - <layout_panel name="inbox_outbox_layout_panel"> - <layout_stack name="inbox_outbox_layout_stack"> - <layout_panel name="inbox_layout_panel"> - <panel label="" name="marketplace_inbox"> - <string name="InboxLabelWithArg"> - å—ã‘å–ã£ãŸå•†å“([NUM]) - </string> - <string name="InboxLabelNoArg"> - å—ã‘å–ã£ãŸå•†å“ - </string> - <button label="å—ã‘å–ã£ãŸå•†å“" name="inbox_btn"/> - <text name="inbox_fresh_new_count"> - [NUM] 個ã®æ–°å•†å“ - </text> - <panel tool_tip="Drag and drop items to your inventory to manage and use them"> - <text name="inbox_inventory_placeholder"> - マーケットプレイスã‹ã‚‰è³¼å…¥ã—ãŸå•†å“ã¯ã“ã“ã«é…é”ã•ã‚Œã¾ã™ã€‚ - </text> - </panel> - </panel> - </layout_panel> - <layout_panel name="outbox_layout_panel"> - <panel label="" name="marketplace_outbox"> - <string name="OutboxLabelWithArg"> - マーãƒãƒ£ãƒ³ãƒˆã®ã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ ([NUM]) - </string> - <string name="OutboxLabelNoArg"> - マーãƒãƒ£ãƒ³ãƒˆã®ã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ - </string> - <button label="マーãƒãƒ£ãƒ³ãƒˆã®ã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹" name="outbox_btn"/> - <button label="" name="outbox_sync_btn" tool_tip="自分ã®ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイス店é ã«ç§»å‹•"/> - <panel> - <panel name="outbox_inventory_placeholder_panel"> - <text name="outbox_inventory_placeholder_title"> - ãƒãƒ¼ãƒ‡ã‚£ãƒ³ã‚°... - </text> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> + <layout_panel name="inbox_layout_panel"> + <panel label="" name="marketplace_inbox"> + <string name="InboxLabelWithArg"> + å—ã‘å–ã£ãŸã‚¢ã‚¤ãƒ†ãƒ ([NUM]) + </string> + <string name="InboxLabelNoArg"> + å—ã‘å–ã£ãŸã‚¢ã‚¤ãƒ†ãƒ + </string> + <button label="å—ã‘å–ã£ãŸã‚¢ã‚¤ãƒ†ãƒ " name="inbox_btn"/> + <text name="inbox_fresh_new_count"> + [NUM] 個ã®æ–°ã‚¢ã‚¤ãƒ†ãƒ + </text> + <panel name="inbox_inventory_placeholder_panel" tool_tip="アイテムを使用ã™ã‚‹ã«ã¯ã€ãã®ã‚¢ã‚¤ãƒ†ãƒ をインベントリã«ãƒ‰ãƒ©ãƒƒã‚°ã‚¢ãƒ³ãƒ‰ãƒ‰ãƒãƒƒãƒ—"> + <text name="inbox_inventory_placeholder"> + マーケットプレイスã‹ã‚‰è³¼å…¥ã—ãŸå•†å“ã¯ã“ã“ã«é…é”ã•ã‚Œã¾ã™ã€‚ + </text> + </panel> + </panel> </layout_panel> </layout_stack> <panel name="button_panel"> @@ -51,7 +28,7 @@ <button label="プãƒãƒ•ã‚£ãƒ¼ãƒ«" name="info_btn" tool_tip="オブジェクトã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’表示ã™ã‚‹"/> </layout_panel> <layout_panel name="share_btn_lp"> - <button label="共有" name="share_btn" tool_tip="「æŒã¡ç‰©ã€ã®ã‚¢ã‚¤ãƒ†ãƒ を共有ã™ã‚‹"/> + <button label="共有" name="share_btn" tool_tip="インベントリã®ã‚¢ã‚¤ãƒ†ãƒ を共有ã™ã‚‹"/> </layout_panel> <layout_panel name="shop_btn_lp"> <button label="店" name="shop_btn" tool_tip="マーケットプレイスã®ã‚µã‚¤ãƒˆã‚’é–‹ã"/> diff --git a/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml b/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml index d820994b59..6931e448b3 100644 --- a/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="item properties" title="アイテムã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«"> <panel.string name="unknown"> (ä¸æ˜Žï¼‰ @@ -16,13 +16,13 @@ [year,datetime,local] [mth,datetime,local] [day,datetime,local] [wkday,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] </panel.string> <panel.string name="origin_inventory"> - (æŒã¡ç‰©ï¼‰ + (インベントリ) </panel.string> <panel.string name="origin_inworld"> (インワールド) </panel.string> <text name="title" value="アイテムã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«"/> - <text name="origin" value="(æŒã¡ç‰©ï¼‰"/> + <text name="origin" value="(インベントリ)"/> <scroll_container name="item_profile_scroll"> <panel label="" name="item_profile"> <text name="LabelItemNameTitle"> diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index c6b033ed95..680ef60890 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -181,8 +181,8 @@ http://secondlife.com/viewer-access-faq </string> <string name="LoginFailedPremiumOnly"> æ—¢ã«ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„るユーザーã«æœ€ä¸Šã®ã‚¤ãƒ³ãƒ¯ãƒ¼ãƒ«ãƒ‰ä½“験をæä¾›ã™ã‚‹ãŸã‚ã€Second Life ã¸ã®ãƒã‚°ã‚¤ãƒ³ã¯ä¸€æ™‚çš„ã«åˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚ - -申ã—訳ã”ã–ã„ã¾ã›ã‚“ãŒã€æœ‰æ–™ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’優先ã™ã‚‹ãŸã‚ã«ã€ç¾æ™‚点ã®ã¨ã“ã‚無料アカウントã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã¯ Second Life ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’ã”é æ…®ã„ãŸã ã„ã¦ã„ã¾ã™ã€‚ + +申ã—訳ã”ã–ã„ã¾ã›ã‚“ãŒã€æœ‰æ–™ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’優先ã™ã‚‹ãŸã‚ã€ç¾åœ¨ã®ã¨ã“ã‚無料アカウントã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã¯ Second Life ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’ã”é æ…®ã„ãŸã ã„ã¦ã„ã¾ã™ã€‚ </string> <string name="LoginFailedComputerProhibited"> ã“ã®ãƒ‘ソコンã‹ã‚‰ã¯ Second Life ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。 @@ -339,17 +339,35 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 アイテム㯠1 ã¤ã ã‘ã“ã“ã«ãƒ‰ãƒ©ãƒƒã‚°ã§ãã¾ã™ </string> <string name="TooltipPrice" value="L$[AMOUNT]:"/> + <string name="TooltipOutboxDragToWorld"> + マーãƒãƒ£ãƒ³ãƒˆãƒœãƒƒã‚¯ã‚¹å†…ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ Rez ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ + </string> <string name="TooltipOutboxNoTransfer"> - ã“れらオブジェクト㮠1 ã¤ã¾ãŸã¯è¤‡æ•°ã¯ã€åˆ¥ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å£²ã‚Šæ¸¡ã—ãŸã‚Šè²æ¸¡ã§ããªã„ã‚‚ã®ã§ã™ã€‚ + ã“れらオブジェクト㮠1 ã¤ã¾ãŸã¯è¤‡æ•°ã¯å£²ã‚Šæ¸¡ã—ãŸã‚Šè²æ¸¡ã—ãŸã‚Šã§ããªã„ã‚‚ã®ã§ã™ã€‚ + </string> + <string name="TooltipOutboxNotInInventory"> + マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã§ã¯ã€ã”自分ã®ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã‹ã‚‰ã®ã‚¢ã‚¤ãƒ†ãƒ ã—ã‹å—ã‘入れるã“ã¨ãŒã§ãã¾ã›ã‚“ </string> <string name="TooltipOutboxWorn"> - ã‚ãªãŸã¯ã“れらオブジェクト㮠1 ã¤ã¾ãŸã¯è¤‡æ•°ã‚’装ç€ã—ã¦ã„ã¾ã™ã€‚ã‚¢ãƒã‚¿ãƒ¼ã‹ã‚‰ãれらをå–り外ã—ã€å†ã³ç§»å‹•ã—ã¦ã¿ã¦ãã ã•ã„。 + ç€ç”¨ã—ã¦ã„るアイテムをマーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«å…¥ã‚Œã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ + </string> + <string name="TooltipOutboxCallingCard"> + コーリングカードをマーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã«å…¥ã‚Œã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ </string> <string name="TooltipOutboxFolderLevels"> - ã“ã®ãƒ•ã‚©ãƒ«ãƒ€ã«ã‚るサブフォルダã®éšŽå±¤ãŒå¤šã™ãŽã¾ã™ã€‚サブフォルダã¯4階層以内(ルートフォルダã®ä¸‹ã«Aã€ãã®ä¸‹ã«Bã€ãã®ä¸‹ã«Cã¨ã„ã†é¢¨ã«ï¼‰ã«ã¾ã¨ã‚ç›´ã—ã¦ãã ã•ã„。 + ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã®æ·±ã•ãŒ 3 を超ãˆã¦ã„ã¾ã™ + </string> + <string name="TooltipOutboxTooManyFolders"> + 最上ä½ãƒ•ã‚©ãƒ«ãƒ€å†…ã®ã‚µãƒ–フォルダ数㌠20 を超ãˆã¦ã„ã¾ã™ </string> <string name="TooltipOutboxTooManyObjects"> - ã“ã®ãƒ•ã‚©ãƒ«ãƒ€ã«ã¯ 200 個以上ã®ã‚ªãƒ–ジェクトãŒå«ã¾ã‚Œã¾ã™ã€‚商å“ã®ã„ã¤ã‹ã‚’ボックスã«å…¥ã‚Œã€ã‚ªãƒ–ジェクト数を減らã—ã¦ãã ã•ã„。 + 最上ä½ãƒ•ã‚©ãƒ«ãƒ€å†…ã®ã‚¢ã‚¤ãƒ†ãƒ 数㌠200 を超ãˆã¦ã„ã¾ã™ + </string> + <string name="TooltipDragOntoOwnChild"> + フォルダをãã®åフォルダã«ç§»å‹•ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ + </string> + <string name="TooltipDragOntoSelf"> + フォルダをãã®ãƒ•ã‚©ãƒ«ãƒ€è‡ªèº«ã«ç§»å‹•ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ </string> <string name="TooltipHttpUrl"> クリックã—ã¦ã“ã® Web ページを見ã¾ã™ @@ -817,6 +835,9 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="anim_yes_head"> é ·ã </string> + <string name="multiple_textures"> + 複数 + </string> <string name="texture_loading"> ãƒãƒ¼ãƒ‡ã‚£ãƒ³ã‚°... </string> @@ -976,6 +997,9 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="choose_the_directory"> å‚ç…§ </string> + <string name="script_files"> + スクリプト + </string> <string name="AvatarSetNotAway"> 一時退å¸ä¸è§£é™¤ </string> @@ -1211,70 +1235,63 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 ã“ã“ã«ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‚’ドラッグã—ã¦ãŠæ°—ã«å…¥ã‚Šã«è¿½åŠ ã—ã¾ã™ã€‚ </string> <string name="InventoryNoTexture"> - 「æŒã¡ç‰©ã€å†…ã«ã“ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ã‚³ãƒ”ーãŒã‚ã‚Šã¾ã›ã‚“ + インベントリ内ã«ã“ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ã‚³ãƒ”ーãŒã‚ã‚Šã¾ã›ã‚“ </string> <string name="InventoryInboxNoItems"> - 購入ã™ã‚‹ãªã©ã—ã¦å–å¾—ã—ãŸã‚¢ã‚¤ãƒ†ãƒ や商å“ã¯ã“ã“ã«è¡¨ç¤ºã•ã‚Œã€æŒã¡ç‰©ã®ãƒ•ã‚©ãƒ«ãƒ€ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ç§»å‹•ã™ã‚‹ã“ã¨ã‚‚ã§ãã‚Œã°ã€è¦ã‚‰ãªããªã£ãŸå ´åˆã«ã¯å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ + マーケットプレイスã§è³¼å…¥ã—ãŸå•†å“ã¯ã“ã“ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ãã®å¾Œã€ã‚¢ã‚¤ãƒ†ãƒ をインベントリã«ãƒ‰ãƒ©ãƒƒã‚°ã™ã‚Œã°ã€ãれらã®ã‚¢ã‚¤ãƒ†ãƒ を使用ã§ãã¾ã™ã€‚ </string> <string name="MarketplaceURL"> - http://marketplace.[DOMAIN_NAME] + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/ </string> <string name="MarketplaceURL_CreateStore"> - http://marketplace.[DOMAIN_NAME]/create_store + http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 </string> - <string name="MarketplaceURL_LearnMore"> - http://marketplace.[DOMAIN_NAME]/learn_more - </string> - <string name="InventoryOutboxCreationErrorTitle"> - マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ãŒæ£ã—ãè¨å®šã•ã‚Œã¦ã„ã¾ã›ã‚“ + <string name="MarketplaceURL_Dashboard"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard </string> - <string name="InventoryOutboxCreationErrorTooltip"> - マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ã®è¨å®šã‚¨ãƒ©ãƒ¼ + <string name="MarketplaceURL_Imports"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports </string> - <string name="InventoryOutboxCreationError"> - å•é¡Œã‚’解決ã™ã‚‹ã«ã¯ã‚«ã‚¹ã‚¿ãƒžãƒ¼ã‚µãƒ¼ãƒ“スã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 + <string name="MarketplaceURL_LearnMore"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more </string> <string name="InventoryOutboxNotMerchantTitle"> - マーケットプレイスã¯çš†ã®å£²ã‚Šå ´ã§ã™ - </string> - <string name="InventoryOutboxNotMerchantTooltip"> - ã‚ãªãŸã‚‚マーãƒãƒ£ãƒ³ãƒˆã«ï¼ + マーケットプレイスã§ã¯èª°ã§ã‚‚アイテムを売るã“ã¨ãŒã§ãã¾ã™ã€‚ </string> + <string name="InventoryOutboxNotMerchantTooltip"/> <string name="InventoryOutboxNotMerchant"> - [[MARKETPLACE_URL] Second Life マーケットプレイス] ã§ã¯ã€SL ä½äººãŒåˆ¶ä½œã—ãŸå•†å“ 100 万点以上ãŒè²©å£²ã•ã‚Œã¦ã„ã¾ã™ã€‚ã‚ãªãŸã‚‚ã”自分ã®è‡ªä¿¡ä½œã‚„ã€ã‚ãªãŸãŒè³¼å…¥ã—ãŸã‚¢ã‚¤ãƒ†ãƒ を商å“ã¨ã—ã¦å£²ã£ã¦ã¿ã¾ã›ã‚“ã‹ã€‚ãã®æ‰‹é †ã¯ç°¡å˜ã§ã€ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã¯ç„¡æ–™ã§ã™ã€‚[[LEARN_MORE_URL] ã“ã¡ã‚‰ã§è©³ç´°ã‚’確ã‹ã‚]ã€ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã«[[CREATE_STORE_URL] ストアを作æˆ] ã—ã¾ã—ょã†ã€‚ + マーãƒãƒ£ãƒ³ãƒˆã«ãªã‚ŠãŸã„æ–¹ã¯ã€[[MARKETPLACE_CREATE_STORE_URL] マーケットプレイスストアを作æˆ]ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ </string> <string name="InventoryOutboxNoItemsTitle"> - マーケットプレイスã¸ã®æ–°ã—ã„出è·æ–¹æ³• - </string> - <string name="InventoryOutboxNoItemsTooltip"> - 商å“ã‚’ã“ã“ã«ãƒ‰ãƒ©ãƒƒã‚°ã‚¢ãƒ³ãƒ‰ãƒ‰ãƒãƒƒãƒ—ã™ã‚‹ã ã‘ã§ã€ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã®å£²ã‚Šç‰©ã¨ãªã‚Šã¾ã™ + アウトボックスã¯ç©ºã§ã™ã€‚ </string> + <string name="InventoryOutboxNoItemsTooltip"/> <string name="InventoryOutboxNoItems"> - 販売ã™ã‚‹å•†å“ã¾ãŸã¯ãƒ•ã‚©ãƒ«ãƒ€ã‚’ã“ã®ã‚¨ãƒªã‚¢ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¾ã™ã€‚コピーä¸å¯ã®ã‚¢ã‚¤ãƒ†ãƒ ã§ãªã„é™ã‚Šã€ãƒ‰ãƒ©ãƒƒã‚°ã—ãŸå•†å“ã®ã‚³ãƒ”ーãŒè¡¨ç¤ºã•ã‚Œã‚‹ã ã‘ã§ã€ã‚ãªãŸã®æŒã¡ç‰©ã‹ã‚‰å•†å“ãŒå®Ÿéš›ã«ç§»å‹•ã™ã‚‹ã‚ã‘ã§ã¯ã‚ã‚Šã¾ã›ã‚“。マーケットプレイスã«å•†å“ã‚’é€ã‚‹æº–å‚™ãŒæ•´ã£ãŸã‚‰ã€ã€Œã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¾ã™ã€‚商å“ã¯ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスインベントリã«ç§»å‹•ã—ãŸæ™‚点ã§ã“ã®ãƒ•ã‚©ãƒ«ãƒ€ã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã™ã€‚ + [[MARKETPLACE_DASHBOARD_URL] マーケットプレイス]ã«è²©å£²ã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ を一覧ã™ã‚‹ã«ã¯ã€ãƒ•ã‚©ãƒ«ãƒ€ã‚’ã“ã®ã‚¨ãƒªã‚¢ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã€ã€Œãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã«é€ä¿¡ã€ã‚’クリックã—ã¾ã™ã€‚ </string> <string name="Marketplace Error None"> エラーãªã— </string> <string name="Marketplace Error Not Merchant"> - エラー:マーケットプレイスã«å•†å“ã‚’é€ã‚‹å‰ã«ã€ã‚ãªãŸè‡ªèº«ã‚’マーãƒãƒ£ãƒ³ãƒˆç™»éŒ²ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼ˆç™»éŒ²ã¯ç„¡æ–™ã§ã™ï¼‰ã€‚ + エラー:マーケットプレイスã«ã‚¢ã‚¤ãƒ†ãƒ ã‚’é€ã‚‹å‰ã«ã€ã‚ãªãŸè‡ªèº«ã‚’マーãƒãƒ£ãƒ³ãƒˆç™»éŒ²ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼ˆç™»éŒ²ã¯ç„¡æ–™ã§ã™ï¼‰ã€‚ </string> <string name="Marketplace Error Empty Folder"> エラー:ã“ã®ãƒ•ã‚©ãƒ«ãƒ€ã¯ç©ºã§ã™ã€‚ </string> <string name="Marketplace Error Unassociated Products"> - エラー:ã‚ãªãŸã®ãƒžãƒ¼ãƒãƒ£ãƒ³ãƒˆã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã¯ã€å•†å“ã¨ç„¡é–¢ä¿‚ã®ã‚¢ã‚¤ãƒ†ãƒ ãŒå¤šã™ãŽã‚‹ãŸã‚ã€ã“ã®ã‚¢ã‚¤ãƒ†ãƒ をアップãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã“ã®ã‚¨ãƒ©ãƒ¼ã‚’解消ã™ã‚‹ã«ã¯ã€ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイスã®ã‚¦ã‚§ãƒ–サイトã«ãƒã‚°ã‚¤ãƒ³ã—ã€å•†å“ã«é–¢ä¿‚ã®ãªã„アイテム数を減らã—ã¦ãã ã•ã„。 + エラー:ã‚ãªãŸã®ãƒžãƒ¼ãƒãƒ£ãƒ³ãƒˆã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã¯ã€å•†å“ã«é–¢é€£ä»˜ã‘られã¦ã„ãªã„アイテムãŒå¤šã™ãŽã‚‹ãŸã‚ã€ã“ã®ã‚¢ã‚¤ãƒ†ãƒ をアップãƒãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã“ã®ã‚¨ãƒ©ãƒ¼ã‚’解消ã™ã‚‹ã«ã¯ã€ãƒžãƒ¼ã‚±ãƒƒãƒˆãƒ—レイス㮠Web サイトã«ãƒã‚°ã‚¤ãƒ³ã—ã€é–¢é€£ä»˜ã‘られã¦ã„ãªã„アイテムã®æ•°ã‚’減らã—ã¦ãã ã•ã„。 </string> <string name="Marketplace Error Object Limit"> - エラー:ã“ã®å•†å“ã«å«ã¾ã‚Œã‚‹ã‚ªãƒ–ジェクトãŒå¤šã™ãŽã¾ã™ã€‚オブジェクトをã„ãã¤ã‹ãƒœãƒƒã‚¯ã‚¹ã«ã¾ã¨ã‚ã€ã‚ªãƒ–ジェクト数を200以下ã«æ¸›ã‚‰ã—ã¦ãã ã•ã„。 + エラー:ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã«å«ã¾ã‚Œã‚‹ã‚ªãƒ–ジェクトãŒå¤šã™ãŽã¾ã™ã€‚オブジェクトをã„ãã¤ã‹ãƒœãƒƒã‚¯ã‚¹ã«ã¾ã¨ã‚ã€ã‚ªãƒ–ジェクト数を200以下ã«æ¸›ã‚‰ã—ã¦ãã ã•ã„。 </string> <string name="Marketplace Error Folder Depth"> - エラー:ã“ã®å•†å“ã¯ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã®éšŽå±¤ãŒå¤šã™ãŽã¾ã™ã€‚ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã‚’ 3 階層以内ã«ã¾ã¨ã‚ç›´ã—ã¦ãã ã•ã„。 + エラー:ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã®éšŽå±¤ãŒå¤šã™ãŽã¾ã™ã€‚ãƒã‚¹ãƒˆå…¥ã‚Šãƒ•ã‚©ãƒ«ãƒ€ã‚’ 3 階層以内ã«ã¾ã¨ã‚ç›´ã—ã¦ãã ã•ã„。 </string> <string name="Marketplace Error Unsellable Item"> - エラー:ã“ã®é …目をマーケットプレイスã§è²©å£²ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 + エラー:ã“ã®ã‚¢ã‚¤ãƒ†ãƒ をマーケットプレイスã§è²©å£²ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 </string> <string name="Marketplace Error Internal Import"> - エラー:ã“ã®å•†å“ã«é–¢ã—ã¦å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ãŠè©¦ã—ãã ã•ã„。 + エラー:ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã«é–¢ã—ã¦å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ãŠè©¦ã—ãã ã•ã„。 </string> <string name="Open landmarks"> ランドマークを開ã @@ -1323,7 +1340,7 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 <string name="No Filters" value="ã„ã„㈠"/> <string name="Since Logoff" value=" - ãƒã‚°ã‚ªãƒ•ä»¥æ¥"/> <string name="InvFolder My Inventory"> - æŒã¡ç‰© + インベントリ </string> <string name="InvFolder Library"> ライブラリ @@ -1356,7 +1373,7 @@ support@secondlife.com ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。 æ–°è¦ãƒ•ã‚©ãƒ«ãƒ€ </string> <string name="InvFolder Inventory"> - æŒã¡ç‰© + インベントリ </string> <string name="InvFolder Uncompressed Images"> 圧縮ã•ã‚Œã¦ã„ãªã„ç”»åƒ @@ -3907,6 +3924,9 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã <string name="Saved_message"> (ä¿å˜æ—¥æ™‚:[LONG_TIMESTAMP]) </string> + <string name="IM_unblock_only_groups_friends"> + ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã™ã‚‹ã«ã¯ã€ã€Œç’°å¢ƒè¨å®šã€ã®ã€Œãƒ—ライãƒã‚·ãƒ¼ã€ã§ã€Œãƒ•ãƒ¬ãƒ³ãƒ‰ã¨ã‚°ãƒ«ãƒ¼ãƒ—以外ã‹ã‚‰ã¯ã‚³ãƒ¼ãƒ«ã¨ IM ã‚’å—ä¿¡ã—ãªã„ã€ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’オフã«ã—ã¾ã™ã€‚ + </string> <string name="answered_call"> 相手ãŒã‚³ãƒ¼ãƒ«ã‚’å—ã‘ã¾ã—㟠</string> @@ -3938,10 +3958,10 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã [AGENT_NAME] ã¨ã‚³ãƒ³ãƒ•ã‚¡ãƒ¬ãƒ³ã‚¹ã™ã‚‹ </string> <string name="inventory_item_offered-im"> - æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ã‚’é€ã‚Šã¾ã—㟠+ インベントリアイテムをé€ã‚Šã¾ã—㟠</string> <string name="share_alert"> - æŒã¡ç‰©ã‹ã‚‰ã“ã“ã«ã‚¢ã‚¤ãƒ†ãƒ をドラッグã—ã¾ã™ + インベントリã‹ã‚‰ã“ã“ã«ã‚¢ã‚¤ãƒ†ãƒ をドラッグã—ã¾ã™ </string> <string name="no_session_message"> (IM セッションãŒå˜åœ¨ã—ã¾ã›ã‚“) @@ -4104,7 +4124,7 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã </string> <string name="uploading_abuse_report"> アップãƒãƒ¼ãƒ‰ä¸... - + å«ŒãŒã‚‰ã›ã®å ±å‘Š </string> <string name="New Shape"> @@ -4370,10 +4390,10 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã </string> <string name="words_separator" value=","/> <string name="server_is_down"> - 大変申ã—訳ã”ã–ã„ã¾ã›ã‚“ãŒã€äºˆæœŸã›ã¬å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ + 大変申ã—訳ã”ã–ã„ã¾ã›ã‚“ãŒã€äºˆæœŸã—ãªã„å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ - status.secondlifegrid.netã§ã€ã‚µãƒ¼ãƒ“スã«é–¢ã™ã‚‹æ—¢çŸ¥ã®å•é¡Œã«ã¤ã„ã¦ãŠèª¿ã¹ãã ã•ã„。 - å•é¡ŒãŒå¼•ã続ã発生ã™ã‚‹å ´åˆã¯ã€ãŠä½¿ã„ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚„ファイアウォールã®è¨å®šã‚’確èªã—ã¦ãã ã•ã„。 + サービスã«é–¢ã™ã‚‹æ—¢çŸ¥ã®å•é¡Œã«ã¤ã„ã¦ã¯ã€status.secondlifegrid.net ã‚’ã”覧ãã ã•ã„。 +å•é¡ŒãŒå¼•ã続ã発生ã™ã‚‹å ´åˆã¯ã€ãŠä½¿ã„ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚„ファイアウォールã®è¨å®šã‚’調ã¹ã¦ãã ã•ã„。 </string> <string name="dateTimeWeekdaysNames"> 日曜日:月曜日:ç«æ›œæ—¥:水曜日:木曜日:金曜日:土曜日 @@ -4825,7 +4845,7 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã ãƒã‚¦ãƒ„ー </string> <string name="Command_Inventory_Label"> - æŒã¡ç‰© + インベントリ </string> <string name="Command_Map_Label"> 地図 @@ -4839,6 +4859,9 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã <string name="Command_Move_Label"> æ©è¡Œ / èµ°è¡Œ / 飛行 </string> + <string name="Command_Outbox_Label"> + マーãƒãƒ£ãƒ³ãƒˆã‚¢ã‚¦ãƒˆãƒœãƒƒã‚¯ã‚¹ + </string> <string name="Command_People_Label"> 人 </string> @@ -4897,7 +4920,7 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã 一般的タスクã®å®Ÿè¡Œæ–¹æ³• </string> <string name="Command_Inventory_Tooltip"> - æŒã¡ç‰©ã‚’表示・使用 + インベントリを表示・使用 </string> <string name="Command_Map_Tooltip"> 世界地図 @@ -4911,6 +4934,9 @@ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãã ã <string name="Command_Move_Tooltip"> ã‚¢ãƒã‚¿ãƒ¼ã®ç§»å‹• </string> + <string name="Command_Outbox_Tooltip"> + 販売用ã«ã‚¢ã‚¤ãƒ†ãƒ をマーケットプレイスã«è»¢é€ + </string> <string name="Command_People_Tooltip"> フレンドã€ã‚°ãƒ«ãƒ¼ãƒ—ã€è¿‘ãã®äºº </string> diff --git a/indra/newview/skins/default/xui/ja/teleport_strings.xml b/indra/newview/skins/default/xui/ja/teleport_strings.xml index 6c69c7a231..64f01f4030 100644 --- a/indra/newview/skins/default/xui/ja/teleport_strings.xml +++ b/indra/newview/skins/default/xui/ja/teleport_strings.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> <teleport_messages> <message_set name="errors"> <message name="invalid_tport"> @@ -45,7 +45,7 @@ テレãƒãƒ¼ãƒˆã®ç›®çš„地を見ã¤ã‘られã¾ã›ã‚“。目的地ãŒä¸€æ™‚çš„ã«åˆ©ç”¨ã§ããªã„状態ã‹ã€ã¾ãŸã¯ã™ã§ã«æ¶ˆæ»…ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚数分後ã«ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。 </message> <message name="no_inventory_host"> - æŒã¡ç‰©ã‚·ã‚¹ãƒ†ãƒ ã¯ç¾åœ¨åˆ©ç”¨ã§ãã¾ã›ã‚“。 + インベントリシステムã¯ç¾åœ¨åˆ©ç”¨ã§ãã¾ã›ã‚“。 </message> </message_set> <message_set name="progress"> diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml index 30d4b0290c..cd0fb4c41b 100644 --- a/indra/newview/skins/default/xui/pt/floater_about_land.xml +++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml @@ -373,7 +373,7 @@ Apenas lotes maiores podem ser listados na busca. </text> <texture_picker label="" name="snapshot_ctrl" tool_tip="Clique para escolher uma imagem"/> <text name="allow_label5"> - e bater papo com avatares neste lote + Avatares em outros lotes podem ver e conversar com avatares neste lote </text> <check_box label="Ver avatares" name="SeeAvatarsCheck" tool_tip="Permite que os avatares em outros lotes vejam e batam papo com avatares neste lote. Você poderá vê-los e conversar com eles."/> <text name="landing_point"> @@ -460,12 +460,12 @@ MÃdia: <text name="Limit access to this parcel to:"> Acesso a este lote </text> - <check_box label="Acesso para público categoria [MATURITY]" name="public_access"/> + <check_box label="Permitir acesso público (Desmarcar esse item cria limites)" name="public_access"/> <text name="Only Allow"> - Restringir acesso a contas confirmardas por: + Permitir acesso apenas para residentes que: </text> - <check_box label="Dados de pagamento fornecidos [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Banir residentes sem identificação."/> - <check_box label="Idade comprovada: [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Banir residentes que não comprovaram a idade. Consulte o [SUPPORT_SITE] para saber mais."/> + <check_box label="Possuam Dados de pagamento fornecidos [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Os residentes devem ter seus dados de pagamento cadastrados para acessar este lote. Consulte o [SUPPORT_SITE] para saber mais."/> + <check_box label="Tiveram sua idade verificada [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Os residentes devem ter a idade verificada para acessar este lote. Consulte o [SUPPORT_SITE] para saber mais."/> <check_box label="Permitir acesso do grupo: [GROUP]" name="GroupCheck" tool_tip="Definir grupo na aba Geral."/> <check_box label="Vender passes para:" name="PassCheck" tool_tip="Permite acesso temporário a este terreno"/> <combo_box name="pass_combo"> diff --git a/indra/newview/skins/default/xui/pt/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/pt/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..05326d8594 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_animation_anim_preview.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Anim Preview" title="ANIMATION.ANIM"> + <text name="name_label"> + Nome: + </text> + <text name="description_label"> + Descrição: + </text> + <button label="Envio (L$[AMOUNT])" name="ok_btn"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_animation_bvh_preview.xml b/indra/newview/skins/default/xui/pt/floater_animation_bvh_preview.xml new file mode 100644 index 0000000000..5cae581045 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_animation_bvh_preview.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Animation Preview"> + <floater.string name="failed_to_initialize"> + Falha ao iniciar animação + </floater.string> + <floater.string name="anim_too_long"> + O arquivo de animação possui [LENGTH] segundos de duração. + +A duração máxima da animação é de [MAX_LENGTH] segundos. + </floater.string> + <floater.string name="failed_file_read"> + Não foi possÃvel ler o arquivo de animação. + +[STATUS] + </floater.string> + <floater.string name="E_ST_OK"> + Ok + </floater.string> + <floater.string name="E_ST_EOF"> + Fim de arquivo prematuro. + </floater.string> + <floater.string name="E_ST_NO_CONSTRAINT"> + ImpossÃvel ler definição constraint. + </floater.string> + <floater.string name="E_ST_NO_FILE"> + ImpossÃvel abrir arquivo BVH. + </floater.string> + <floater.string name="E_ST_NO_HIER"> + Invalid HIERARCHY header. + </floater.string> + <floater.string name="E_ST_NO_JOINT"> + RAIZ ou JUNTA não encontrados. + </floater.string> + <floater.string name="E_ST_NO_NAME"> + ImpossÃvel obter nome JOINT. + </floater.string> + <floater.string name="E_ST_NO_OFFSET"> + ImpossÃvel localizar OFFSET. + </floater.string> + <floater.string name="E_ST_NO_CHANNELS"> + ImpossÃvel localizar CHANNELS. + </floater.string> + <floater.string name="E_ST_NO_ROTATION"> + ImpossÃvel obter ordem de rotação. + </floater.string> + <floater.string name="E_ST_NO_AXIS"> + ImpossÃvel obter eixo de rotação. + </floater.string> + <floater.string name="E_ST_NO_MOTION"> + ImpossÃvel localizar MOTION. + </floater.string> + <floater.string name="E_ST_NO_FRAMES"> + ImpossÃvel determinar número de quadros. + </floater.string> + <floater.string name="E_ST_NO_FRAME_TIME"> + ImpossÃvel determinar tempo dos quadros. + </floater.string> + <floater.string name="E_ST_NO_POS"> + ImpossÃvel definir posicionamento. + </floater.string> + <floater.string name="E_ST_NO_ROT"> + ImpossÃvel definir valores da rotação. + </floater.string> + <floater.string name="E_ST_NO_XLT_FILE"> + ImpossÃvel abrir arquivo de tradução. + </floater.string> + <floater.string name="E_ST_NO_XLT_HEADER"> + ImpossÃvel ler cabeçalho de tradução. + </floater.string> + <floater.string name="E_ST_NO_XLT_NAME"> + ImpossÃvel ler nomes traduzidos. + </floater.string> + <floater.string name="E_ST_NO_XLT_IGNORE"> + ImpossÃvel obter valor traduzido a ignorar. + </floater.string> + <floater.string name="E_ST_NO_XLT_RELATIVE"> + ImpossÃvel obter valor traduzido relativo. + </floater.string> + <floater.string name="E_ST_NO_XLT_OUTNAME"> + ImpossÃvel obter valor traduzido. + </floater.string> + <floater.string name="E_ST_NO_XLT_MATRIX"> + ImpossÃvel ler matriz de tradução. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGECHILD"> + ImpossÃvel obter nome mergechild. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGEPARENT"> + ImpossÃvel obter nome mergeparent. + </floater.string> + <floater.string name="E_ST_NO_XLT_PRIORITY"> + ImpossÃvel obter valor prioritário. + </floater.string> + <floater.string name="E_ST_NO_XLT_LOOP"> + ImpossÃvel obter valor do loop. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEIN"> + ImpossÃvel obter valor easeIn. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEOUT"> + ImpossÃvel obter valor easeOut. + </floater.string> + <floater.string name="E_ST_NO_XLT_HAND"> + ImpossÃvel obter valor de morph da mão. + </floater.string> + <floater.string name="E_ST_NO_XLT_EMOTE"> + ImpossÃvel ler nome do emote. + </floater.string> + <floater.string name="E_ST_BAD_ROOT"> + Nome da junta incorreto, use "quadril". + </floater.string> + <text name="name_label"> + Nome: + </text> + <text name="description_label"> + Descrição: + </text> + <spinner label="Prioridade" name="priority" tool_tip="Controla quais animações podem ser interrompidas por esta animação"/> + <check_box label="Loop" name="loop_check" tool_tip="Executa esta animação sem parar"/> + <spinner label="Dentro(%)" name="loop_in_point" tool_tip="Define o ponto em que a animação em loop reinicia"/> + <spinner label="Fora(%)" name="loop_out_point" tool_tip="Define o ponto em que a animação em loop acaba"/> + <text name="hand_label"> + Pose das mãos + </text> + <combo_box name="hand_pose_combo" tool_tip="Controla os gestos das mãos durante a animação"> + <combo_box.item label="Abrir" name="Spread"/> + <combo_box.item label="Relaxado" name="Relaxed"/> + <combo_box.item label="Apontar ambas" name="PointBoth"/> + <combo_box.item label="Punho" name="Fist"/> + <combo_box.item label="E relaxada" name="RelaxedLeft"/> + <combo_box.item label="Apontar E" name="PointLeft"/> + <combo_box.item label="Punho E" name="FistLeft"/> + <combo_box.item label="D relaxada" name="RelaxedRight"/> + <combo_box.item label="Apontar D" name="PointRight"/> + <combo_box.item label="Punho D" name="FistRight"/> + <combo_box.item label="Saudação D" name="SaluteRight"/> + <combo_box.item label="Escrevendo" name="Typing"/> + <combo_box.item label="Paz D" name="PeaceRight"/> + </combo_box> + <text name="emote_label"> + Expressão + </text> + <combo_box name="emote_combo" tool_tip="Controla as expressões faciais durante a animação"> + <item label="(nenhum)" name="[None]" value=""/> + <item label="Aaaaah" name="Aaaaah" value="Aaaaah"/> + <item label="Com medo" name="Afraid" value="Com medo"/> + <item label="Bravo" name="Angry" value="Bravo"/> + <item label="Sorriso contagiante" name="BigSmile" value="Sorriso contagiante"/> + <item label="À toa" name="Bored" value="À toa"/> + <item label="Chorar" name="Cry" value="Chorar"/> + <item label="Desdenho" name="Disdain" value="Desdenho"/> + <item label="Com vergonha" name="Embarrassed" value="Com vergonha"/> + <item label="Franzir testa" name="Frown" value="Franzir testa"/> + <item label="Beijo" name="Kiss" value="Beijo"/> + <item label="Rir" name="Laugh" value="Rir"/> + <item label="Mostrar a lÃngua" name="Plllppt" value="Mostrar a lÃngua"/> + <item label="Asco" name="Repulsed" value="Asco"/> + <item label="Triste" name="Sad" value="Triste"/> + <item label="Encolher os ombros" name="Shrug" value="Encolher os ombros"/> + <item label="Sorriso" name="Smile" value="Sorriso"/> + <item label="Surpresa" name="Surprise" value="Surpresa"/> + <item label="Piscar" name="Wink" value="Piscar"/> + <item label="Preocupado" name="Worry" value="Preocupado"/> + </combo_box> + <text name="preview_label"> + Visualizar enquanto + </text> + <combo_box name="preview_base_anim" tool_tip="Use para testar o comportamento de sua animação enquanto seu avatar executa ações comuns."> + <item label="Em pé" name="Standing" value="Em pé"/> + <item label="Andar" name="Walking" value="Andar"/> + <item label="Sentado" name="Sitting" value="Sentado"/> + <item label="Voar" name="Flying" value="Voar"/> + </combo_box> + <spinner label="Aproximação (seg)" name="ease_in_time" tool_tip="Tempo (em segundos) da transição inicial da animação"/> + <spinner label="Afastamento (seg)" name="ease_out_time" tool_tip="Tempo (em segundos) da transição de saÃda da animação"/> + <button name="play_btn" tool_tip="Executar animação"/> + <button name="pause_btn" tool_tip="Pausar a animação"/> + <button name="stop_btn" tool_tip="Interromper a execução da animação"/> + <text name="bad_animation_text"> + Não foi possÃvel ler o arquivo de animação. + +Recomendamos que os arquivos BVH sejam exportados do Poser 4. + </text> + <button label="Envio (L$[AMOUNT])" name="ok_btn"/> + <button label="Cancelar" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/pt/floater_merchant_outbox.xml new file mode 100644 index 0000000000..bb6113671b --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_merchant_outbox.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_merchant_outbox" title="CAIXA DE SAÃDA DO LOJISTA"> + <string name="OutboxFolderCount1"> + 1 pasta + </string> + <string name="OutboxFolderCountN"> + [NUM] pasta(s) + </string> + <string name="OutboxImporting"> + Enviando pastas... + </string> + <string name="OutboxInitializing"> + Iniciando... + </string> + <panel label=""> + <panel> + <panel name="outbox_inventory_placeholder_panel"> + <text name="outbox_inventory_placeholder_title"> + Carregando... + </text> + </panel> + </panel> + <panel> + <button label="Enviar para Mercado" name="outbox_import_btn" tool_tip="Enviar para a Frente da loja do meu Mercado"/> + </panel> + </panel> +</floater> 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 498058f933..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="header_panel"> - <text name="header_text"> - Escolher arquivo de modelo - </text> - </panel> - <panel name="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="header_panel"> - <text name="header_text"> - Otimizar modelo - </text> - </panel> - <text name="description"> - O modelo foi ajustado para desempenho. Faça novos ajustes, se desejar. - </text> - <panel name="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="header_panel"> - <text name="header_text"> - Ajustar fÃsico - </text> - </panel> - <text name="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="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="header_panel"> - <text name="header_text"> - Revisar - </text> - </panel> - <panel name="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="header_panel"> - <text name="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_preview_animation.xml b/indra/newview/skins/default/xui/pt/floater_preview_animation.xml index b650b7945c..19474d8099 100644 --- a/indra/newview/skins/default/xui/pt/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/pt/floater_preview_animation.xml @@ -6,6 +6,6 @@ <text name="desc txt"> Descrição: </text> - <button label="Tocar inworld" label_selected="Parar" name="Anim play btn" tool_tip="Tocar essa animação de forma que outros possam ver" width="131"/> - <button label="Executar localmente" label_selected="Parar" left="162" name="Anim audition btn" tool_tip="Tocar essa animação de forma que apenas você possa ver" width="120"/> + <button label="Tocar inworld" label_selected="Parar" name="Inworld" tool_tip="Executar essa animação de forma que outros possam ver"/> + <button label="Tocar localmente" label_selected="Parar" name="Locally" tool_tip="Executar animação de forma que apenas você possa ver"/> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/pt/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..b479d5f6d6 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_test_layout_stacks.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="LAYOUTSTACK TESTS"/> diff --git a/indra/newview/skins/default/xui/pt/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/pt/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..dd282bf1fc --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_test_text_vertical_aligment.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="JANELA DE TESTE"/> diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml index f35f31f5f7..4b31833602 100644 --- a/indra/newview/skins/default/xui/pt/floater_tools.xml +++ b/indra/newview/skins/default/xui/pt/floater_tools.xml @@ -1,5 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="toolbox floater" short_title="BUILD TOOLS" title=""> + <floater.string name="grid_screen_text"> + Tela + </floater.string> + <floater.string name="grid_local_text"> + Local + </floater.string> + <floater.string name="grid_world_text"> + Mundo + </floater.string> + <floater.string name="grid_reference_text"> + Referência + </floater.string> + <floater.string name="grid_attachment_text"> + Anexo + </floater.string> <floater.string name="status_rotate"> Arrastar as faixas coloridas para girar o objeto </floater.string> @@ -63,7 +78,12 @@ </text> <check_box initial_value="true" label="Esticar texturas" name="checkbox stretch textures"/> <check_box initial_value="true" label="Ajustar" name="checkbox snap to grid"/> - <button label="Opções..." label_selected="Opções..." name="Options..." tool_tip="Mais opções de grade"/> + <combo_box name="combobox grid mode" tool_tip="Selecione o tipo de régua da grade onde o objeto será colocado"> + <combo_box.item label="Mundo" name="World"/> + <combo_box.item label="Local" name="Local"/> + <combo_box.item label="Referência" name="Reference"/> + </combo_box> + <button label="" label_selected="Opções..." name="Options..." tool_tip="Mais opções de grade"/> <button label="" label_selected="" name="ToolCube" tool_tip="Cubo"/> <button label="" label_selected="" name="ToolPrism" tool_tip="Prisma"/> <button label="" label_selected="" name="ToolPyramid" tool_tip="Pirâmide"/> diff --git a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml b/indra/newview/skins/default/xui/pt/floater_voice_effect.xml index 4f01600d9f..b29ca3d699 100644 --- a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/pt/floater_voice_effect.xml @@ -42,13 +42,16 @@ <string name="effect_Demon"> Demônio </string> + <string name="effect_Female Elf"> + Elfa + </string> <string name="effect_Flirty"> Paquerador </string> <string name="effect_Foxy"> Sensual </string> - <string name="effect_Halloween_2010_Bonus"> + <string name="effect_Halloween 2010 Bonus"> Bônus_Halloween_2010 </string> <string name="effect_Helium"> @@ -57,9 +60,18 @@ <string name="effect_Husky"> Rouco </string> + <string name="effect_Husky Whisper"> + Sussurro rouco + </string> <string name="effect_Intercom"> Interfone </string> + <string name="effect_Julia"> + Julia + </string> + <string name="effect_Lo Lilt"> + Cantarolado baixo + </string> <string name="effect_Macho"> Macho </string> @@ -69,6 +81,9 @@ <string name="effect_Mini"> Mini </string> + <string name="effect_Model"> + Modelo + </string> <string name="effect_Nano"> Nano </string> @@ -90,6 +105,9 @@ <string name="effect_Roxanne"> Roxanne </string> + <string name="effect_Rumble"> + Ronco + </string> <string name="effect_Sabrina"> Sabrina </string> @@ -102,6 +120,9 @@ <string name="effect_Shorty"> Baixinho </string> + <string name="effect_Smaller"> + Menor + </string> <string name="effect_Sneaky"> Sorrateiro </string> diff --git a/indra/newview/skins/default/xui/pt/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/pt/menu_inspect_object_gear.xml index 184db26538..7e271904e9 100644 --- a/indra/newview/skins/default/xui/pt/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/pt/menu_inspect_object_gear.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<menu name="Gear Menu"> +<toggleable_menu name="Gear Menu"> <menu_item_call label="Tocar" name="touch"/> <menu_item_call label="Sentar" name="sit"/> <menu_item_call label="Pagar" name="pay"/> @@ -12,7 +12,8 @@ <menu_item_call label="Adicionar" name="add"/> <menu_item_call label="Denunciar" name="report"/> <menu_item_call label="Bloquear" name="block"/> + <menu_item_call label="Desbloquear" name="unblock"/> <menu_item_call label="Mais zoom" name="zoom_in"/> <menu_item_call label="Tirar" name="remove"/> <menu_item_call label="Mais informações" name="more_info"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_inventory.xml b/indra/newview/skins/default/xui/pt/menu_inventory.xml index ba3879b5a1..09e1fbf72e 100644 --- a/indra/newview/skins/default/xui/pt/menu_inventory.xml +++ b/indra/newview/skins/default/xui/pt/menu_inventory.xml @@ -59,6 +59,7 @@ <menu_item_call label="Propriedades" name="Properties"/> <menu_item_call label="Renomear" name="Rename"/> <menu_item_call label="Copiar item UUID" name="Copy Asset UUID"/> + <menu_item_call label="Cortar" name="Cut"/> <menu_item_call label="Copiar" name="Copy"/> <menu_item_call label="Colar" name="Paste"/> <menu_item_call label="Colar como link" name="Paste As Link"/> @@ -84,6 +85,6 @@ <menu_item_call label="Adicionar" name="Wearable Add"/> <menu_item_call label="Tirar" name="Take Off"/> <menu_item_call label="Copiar para Caixa de saÃda do lojista" name="Merchant Copy"/> - <menu_item_call label="Mover para Caixa de saÃda do lojista" name="Merchant Move"/> + <menu_item_call label="Enviar para Mercado" name="Marketplace Send"/> <menu_item_call label="--Sem opções--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/pt/menu_login.xml b/indra/newview/skins/default/xui/pt/menu_login.xml index 94195f1b8c..be94ad49db 100644 --- a/indra/newview/skins/default/xui/pt/menu_login.xml +++ b/indra/newview/skins/default/xui/pt/menu_login.xml @@ -16,8 +16,8 @@ <menu_item_call label="Definir tamanho da janela:" name="Set Window Size..."/> <menu_item_call label="Mostrar TOS" name="TOS"/> <menu_item_call label="Mostrar mensagem crÃtica" name="Critical"/> - <menu_item_call label="Teste de mÃdia do navegador" name="Web Browser Test"/> <menu_item_call label="Test de Bugs de Conteúdo Web" name="Web Content Floater Debug Test"/> + <menu label="Configurar nÃvel de registro em log" name="Set Logging Level"/> <menu_item_check label="Exibir seletor da grade" name="Show Grid Picker"/> <menu_item_call label="Exibir painel de notificações" name="Show Notifications Console"/> </menu> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index 119a3bdcfe..fd973bf3c2 100644 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -14,14 +14,14 @@ <menu_item_check label="Voar" name="Fly"/> <menu_item_check label="Correr sempre" name="Always Run"/> <menu_item_call label="Parar minha animação" name="Stop Animating My Avatar"/> + <menu_item_call label="Andar/correr/voar..." name="Walk / run / fly"/> </menu> <menu label="Status" name="Status"> <menu_item_call label="Ausente" name="Set Away"/> <menu_item_call label="Ocupado" name="Set Busy"/> </menu> - <menu_item_call label="Request Admin Status" name="Request Admin Options"/> - <menu_item_call label="Sair do modo admin" name="Leave Admin Options"/> - <menu_item_call label="Comprar L$" name="Buy and Sell L$"/> + <menu_item_call label="Comprar L$..." name="Buy and Sell L$"/> + <menu_item_call label="Caixa de saÃda do lojista..." name="MerchantOutbox"/> <menu_item_call label="Painel da conta..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=pt"/> </menu_item_call> @@ -63,10 +63,10 @@ <menu_item_check label="Propriedades do lote" name="Parcel Properties"/> <menu_item_check label="Menu avançado" name="Show Advanced Menu"/> </menu> - <menu label="Sol" name="Environment Settings"> + <menu label="Sol" name="Sun"> <menu_item_call label="Amanhecer" name="Sunrise"/> <menu_item_call label="Meio-dia" name="Noon"/> - <menu_item_call label="Pôr-do-Sol" name="Sunset"/> + <menu_item_call label="Pôr-do-sol" name="Sunset"/> <menu_item_call label="Meia-noite" name="Midnight"/> <menu_item_call label="Usar configurações da região" name="Use Region Settings"/> </menu> @@ -118,7 +118,7 @@ <menu_item_call label="Devolver objeto" name="Return Object back to Owner"/> </menu> <menu label="Scripts" name="Scripts"> - <menu_item_call label="Recompilar scripts (LSL)" name="Mono"/> + <menu_item_call label="Recompilar scripts (Mono)" name="Mono"/> <menu_item_call label="Recompilar scripts (LSL)" name="LSL"/> <menu_item_call label="Resetar scripts" name="Reset Scripts"/> <menu_item_call label="Scripts em modo execução" name="Set Scripts to Running"/> @@ -163,7 +163,7 @@ <menu_item_check label="Limitar distância da seleção" name="Limit Select Distance"/> <menu_item_check label="Disable Camera Constraints" name="Disable Camera Distance"/> <menu_item_check label="Foto de alta resolução" name="HighResSnapshot"/> - <menu_item_check label="Compactar fotos para HD" name="QuietSnapshotsToDisk"/> + <menu_item_check label="Fotos sem barulho para HD" name="QuietSnapshotsToDisk"/> <menu label="Ferramentas de desempenho" name="Performance Tools"> <menu_item_call label="Medidor de lag" name="Lag Meter"/> <menu_item_check label="Barra de estatÃsticas" name="Statistics Bar"/> @@ -178,22 +178,22 @@ <menu_item_check label="Mostrar retÃculo na vista subjetiva" name="ShowCrosshairs"/> </menu> <menu label="Tipos de renderização" name="Rendering Types"> - <menu_item_check label="Simples" name="Simple"/> - <menu_item_check label="Alpha" name="Alpha"/> - <menu_item_check label="Ãrvore" name="Tree"/> - <menu_item_check label="Avatares" name="Character"/> - <menu_item_check label="Patch de superfÃcie" name="Surface Patch"/> - <menu_item_check label="Céu" name="Sky"/> - <menu_item_check label="Ãgua" name="Water"/> - <menu_item_check label="Chão" name="Ground"/> - <menu_item_check label="Volume" name="Volume"/> - <menu_item_check label="Grama" name="Grass"/> - <menu_item_check label="Nuvens" name="Clouds"/> - <menu_item_check label="PartÃculas" name="Particles"/> - <menu_item_check label="Elevação" name="Bump"/> + <menu_item_check label="Simples" name="Rendering Type Simple"/> + <menu_item_check label="Alpha" name="Rendering Type Alpha"/> + <menu_item_check label="Ãrvore" name="Rendering Type Tree"/> + <menu_item_check label="Avatares" name="Rendering Type Character"/> + <menu_item_check label="Patch de superfÃcie" name="Rendering Type Surface Patch"/> + <menu_item_check label="Céu" name="Rendering Type Sky"/> + <menu_item_check label="Ãgua" name="Rendering Type Water"/> + <menu_item_check label="Chão" name="Rendering Type Ground"/> + <menu_item_check label="Volume" name="Rendering Type Volume"/> + <menu_item_check label="Grama" name="Rendering Type Grass"/> + <menu_item_check label="Nuvens" name="Rendering Type Clouds"/> + <menu_item_check label="PartÃculas" name="Rendering Type Particles"/> + <menu_item_check label="Elevação" name="Rendering Type Bump"/> </menu> <menu label="Recursos de renderização" name="Rendering Features"> - <menu_item_check label="Interface" name="UI"/> + <menu_item_check label="Interface" name="ToggleUI"/> <menu_item_check label="Selecionado" name="Selected"/> <menu_item_check label="Realçado" name="Highlighted"/> <menu_item_check label="Texturas dinâmicas" name="Dynamic Textures"/> @@ -206,8 +206,6 @@ <menu_item_check label="Smoothing de mouse" name="Mouse Smoothing"/> <menu_item_call label="Liberar teclas" name="Release Keys"/> <menu label="Atalhos" name="Shortcuts"> - <menu_item_call label="Imagem (L$[COST])..." name="Upload Image"/> - <menu_item_check label="Busca" name="Search"/> <menu_item_check label="Mostrar menu avançado - atalho antigo" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Fechar janela" name="Close Window"/> <menu_item_call label="Fechar todas as janelas" name="Close All Windows"/> @@ -216,13 +214,6 @@ <menu_item_check label="Flycam Joystick" name="Joystick Flycam"/> <menu_item_call label="Visão padrão" name="Reset View"/> <menu_item_call label="Olhar para quem fala por último" name="Look at Last Chatter"/> - <menu label="Selecionar ferramenta de construção" name="Select Tool"> - <menu_item_call label="Ferramenta enfoque" name="Focus"/> - <menu_item_call label="Ferramenta de movimentação" name="Move"/> - <menu_item_call label="Ferramenta de edição" name="Edit"/> - <menu_item_call label="Ferramenta criar" name="Create"/> - <menu_item_call label="Ferramenta de terrenos" name="Land"/> - </menu> <menu_item_call label="Mais zoom" name="Zoom In"/> <menu_item_call label="Zoom padrão" name="Zoom Default"/> <menu_item_call label="Menos zoom" name="Zoom Out"/> @@ -278,6 +269,7 @@ <menu_item_check label="Fila de construção" name="Build Queue"/> <menu_item_check label="Vetores de vento" name="Wind Vectors"/> <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> <menu label="Rendering" name="Rendering"> @@ -300,11 +292,10 @@ <menu_item_call label="Drop a Packet" name="Drop a Packet"/> </menu> <menu_item_call label="Empurrões, trombadas e tapas" name="Bumps, Pushes &amp; Hits"/> - <menu label="Mundo" name="World"> - <menu_item_check label="Impor sobre sol regional" name="Sim Sun Override"/> - <menu_item_check label="Efeito baliza piscando" name="Cheesy Beacon"/> - <menu_item_check label="Fixed Weather" name="Fixed Weather"/> - <menu_item_call label="Dump Region Object Cache" name="Dump Region Object Cache"/> + <menu label="Mundo" name="DevelopWorld"> + <menu_item_check label="Impor sobre sol de simulação" name="Sim Sun Override"/> + <menu_item_check label="Clima fixo" name="Fixed Weather"/> + <menu_item_call label="Descartar cache do objeto de região" name="Dump Region Object Cache"/> </menu> <menu label="Interface" name="UI"> <menu_item_call label="Teste de mÃdia do navegador" name="Web Browser Test"/> @@ -324,11 +315,11 @@ </menu> <menu label="Avatar" name="Character"> <menu label="Grab Baked Texture" name="Grab Baked Texture"> - <menu_item_call label="Ãris" name="Iris"/> - <menu_item_call label="Cabeça" name="Head"/> - <menu_item_call label="Cintura acima" name="Upper Body"/> - <menu_item_call label="Cintura para baixo" name="Lower Body"/> - <menu_item_call label="Saia" name="Skirt"/> + <menu_item_call label="Ãris" name="Grab Iris"/> + <menu_item_call label="Cabeça" name="Grab Head"/> + <menu_item_call label="Cintura acima" name="Grab Upper Body"/> + <menu_item_call label="Cintura para baixo" name="Grab Lower Body"/> + <menu_item_call label="Saia" name="Grab Skirt"/> </menu> <menu label="Testes de personagem" name="Character Tests"> <menu_item_call label="Toggle Character Geometry" name="Toggle Character Geometry"/> @@ -344,18 +335,27 @@ </menu> <menu_item_check label="Texturas HTTP" name="HTTP Textures"/> <menu_item_check label="Inventário HTTP" name="HTTP Inventory"/> + <menu_item_call label="Habilitar Visual Leak Detector" name="Enable Visual Leak Detector"/> <menu_item_check label="Console Window on next Run" name="Console Window"/> + <menu label="Configurar nÃvel de registro em log" name="Set Logging Level"> + <menu_item_check label="Depurar" name="Debug"/> + <menu_item_check label="Info" name="Info"/> + <menu_item_check label="Aviso" name="Warning"/> + <menu_item_check label="Error" name="Error"/> + <menu_item_check label="Nenhum" name="None"/> + </menu> <menu_item_call label="Request Admin Status" name="Request Admin Options"/> <menu_item_call label="Sair do modo admin" name="Leave Admin Options"/> <menu_item_check label="Mostrar menu admin" name="View Admin Options"/> </menu> <menu label="Admin" name="Admin"> - <menu label="Object"> - <menu_item_call label="Pegar uma cópia" name="Take Copy"/> - <menu_item_call label="Force Owner To Me" name="Force Owner To Me"/> - <menu_item_call label="Force Owner Permissive" name="Force Owner Permissive"/> + <menu label="Objeto" name="AdminObject"> + <menu_item_call label="Pegar uma cópia" name="Admin Take Copy"/> + <menu_item_call label="Forçar propriedade para mim" name="Force Owner To Me"/> + <menu_item_call label="Forçar permissão de proprietário" name="Force Owner Permissive"/> <menu_item_call label="Excluir" name="Delete"/> <menu_item_call label="Bloquear" name="Lock"/> + <menu_item_call label="Obter IDs dos bens" name="Get Assets IDs"/> </menu> <menu label="Lote" name="Parcel"> <menu_item_call label="Force Owner To Me" name="Owner To Me"/> @@ -372,5 +372,16 @@ <menu label="Take Off Clothing" name="Take Off Clothing"> <menu_item_call label="FÃsico" name="Physics"/> </menu> + <menu label="Ajuda" name="DeprecatedHelp"> + <menu_item_call label="Blog oficial da Linden" name="Official Linden Blog"/> + <menu_item_call label="Portal de scripts" name="Scripting Portal"/> + <menu label="Relatar bugs" name="Bug Reporting"> + <menu_item_call label="Monitor de problemas" name="Public Issue Tracker"/> + <menu_item_call label="Ajuda do monitor de problemas" name="Publc Issue Tracker Help"/> + <menu_item_call label="Relatório de bugs 101" name="Bug Reporing 101"/> + <menu_item_call label="Problemas de segurança" name="Security Issues"/> + <menu_item_call label="Página Wiki" name="QA Wiki"/> + </menu> + </menu> </menu> </menu_bar> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 2c5ccd6e19..3b39c0f92c 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -85,17 +85,38 @@ Verifique se a conexão à internet está funcionando. <usetemplate canceltext="Cancelar" name="yesnocancelbuttons" notext="Não salvar" yestext="Salvar"/> </notification> <notification name="ConfirmNoCopyToOutbox"> - Você não tem permissão para copiar este item para a Caixa de saÃda do lojista. Tem certeza de que deseja mover o itens a seguir? - [ITEM_NAME] - <usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/> + Você não possui permissão para copiar um ou mais destes itens para a Caixa de saÃda do lojista. Você pode movê-los ou abandoná-los. + <usetemplate name="okcancelbuttons" notext="Não mover item(ns)" yestext="Mover item(ns)"/> + </notification> + <notification name="OutboxFolderCreated"> + Uma nova pasta foi criada para cada item transferido para o nÃvel superior de sua Caixa de saÃda do lojista. + <usetemplate ignoretext="Uma nova pasta foi criada na Caixa de saÃda do lojista" name="okignore" yestext="OK"/> </notification> - <notification name="OutboxUploadComplete"> - Envio para Mercado concluÃdo. - <usetemplate name="okbutton" yestext="Viva!"/> + <notification name="OutboxImportComplete"> + Êxito + +Todas as pastas foram enviadas para o Mercado com êxito. + <usetemplate ignoretext="Todas as pastas enviadas para o Mercado" name="okignore" yestext="OK"/> </notification> - <notification name="OutboxUploadHadErrors"> - Envio para Mercado concluÃdo com erros! Corrija os problemas em sua caixa de saÃda e tente novamente. Obrigado. - <usetemplate name="okbutton" yestext="Tudo bem!"/> + <notification name="OutboxImportHadErrors"> + Algumas pastas não foram transferidas + +Erro ao enviar algumas pastas para o Mercado. Estas pastas ainda estão na sua Caixa de saÃda do lojista. + +Consulte o [[MARKETPLACE_IMPORTS_URL] log de erros] para mais informações. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxImportFailed"> + Falha de transferência + +Nenhuma pasta enviada para o Mercado devido a um erro do sistema ou da rede. Tente novamente mais tarde. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="OutboxInitFailed"> + Falha na inicialização do Mercado + +Falha na inicialização do mercado devido a um erro do sistema ou da rede. Tente novamente mais tarde. + <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="CompileQueueSaveText"> Houve um problema com o carregamento do texto para um script devido à seguinte razão: [REASON]. Por favor, tente novamente mais tarde. @@ -643,7 +664,7 @@ Esperada [VALIDS] Incapaz de criar arquivo de saÃda: [FILE] </notification> <notification name="DoNotSupportBulkAnimationUpload"> - O [APP_NAME] ainda não faz o upload de vários arquivos de animação de uma vez. + O [APP_NAME] ainda não faz o upload de vários arquivos de animação no formato BVH de uma vez. </notification> <notification name="CannotUploadReason"> Incapaz de carregar [FILE] devido ao seguinte motivo: [REASON] @@ -1424,8 +1445,7 @@ Para instalar a atualização, será preciso reiniciar o [APP_NAME]. <usetemplate ignoretext="Confirmar antes de devolver objetos a seus donos" name="okcancelignore" notext="Cancelar" yestext="Retornar"/> </notification> <notification name="GroupLeaveConfirmMember"> - Você é atualmente um membro do grupo <nolink>[GROUP]</nolink>. -Sair do grupo? + Você é atualmente um membro do grupo <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Sair"/> </notification> <notification name="ConfirmKick"> @@ -2592,16 +2612,16 @@ Deseja aceitar? '<nolink>[TITLE]</nolink>' de [NAME] [MESSAGE] <form name="form"> - <button name="Mute" text="Bloquear"/> - <button name="Ignore" text="Ignorar"/> + <button name="Client_Side_Mute" text="Bloquear"/> + <button name="Client_Side_Ignore" text="Ignorar"/> </form> </notification> <notification name="ScriptDialogGroup"> <nolink>[TITLE]</nolink>' de [GROUPNAME]' [MESSAGE] <form name="form"> - <button name="Mute" text="Bloquear"/> - <button name="Ignore" text="Ignorar"/> + <button name="Client_Side_Mute" text="Bloquear"/> + <button name="Client_Side_Ignore" text="Ignorar"/> </form> </notification> <notification name="BuyLindenDollarSuccess"> @@ -2799,6 +2819,12 @@ Com os seguintes residentes: [RESIDENTS] <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> </notification> + <notification name="ShareFolderConfirmation"> + Apenas uma pasta pode ser compartilhada por vez. + +Tem certeza de que quer compartilhar os itens abaixo? + <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> + </notification> <notification name="ItemsShared"> Itens compartilhados. </notification> diff --git a/indra/newview/skins/default/xui/pt/panel_nearby_chat.xml b/indra/newview/skins/default/xui/pt/panel_nearby_chat.xml index 15470dc94a..6828d41dee 100644 --- a/indra/newview/skins/default/xui/pt/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/pt/panel_nearby_chat.xml @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="nearby_chat"> - <check_box label="Traduzir bate-papo" name="translate_chat_checkbox"/> + <layout_stack name="stack"> + <layout_panel name="translate_chat_checkbox_lp"> + <check_box label="Traduzir bate-papo" name="translate_chat_checkbox"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/pt/panel_region_estate.xml b/indra/newview/skins/default/xui/pt/panel_region_estate.xml index e5d394865c..6c5945aa15 100644 --- a/indra/newview/skins/default/xui/pt/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/pt/panel_region_estate.xml @@ -23,10 +23,10 @@ <check_box label="Permitir acesso público" name="externally_visible_check"/> <button label="?" name="externally_visible_help"/> <text name="Only Allow"> - Restringir acesso a contas confirmardas por: + Permitir acesso apenas para residentes que: </text> - <check_box label="Dados de pagamento fornecidos" name="limit_payment" tool_tip="Banir residentes sem identificação."/> - <check_box label="Verificação de idade" name="limit_age_verified" tool_tip="Banir residentes que não comprovaram a idade. Consulte o [SUPPORT_SITE] para saber mais."/> + <check_box label="Dados de pagamento constam no registro." name="limit_payment" tool_tip="Propriedade de acesso restrito a residentes que já cadastraram seus dados de pagamento Consulte o [SUPPORT_SITE] para saber mais."/> + <check_box label="A idade foi verificada" name="limit_age_verified" tool_tip="Residentes devem ter a idade verificada para acessar esta propriedade. Consulte o [SUPPORT_SITE] para saber mais."/> <check_box label="Permitir conversa de voz" name="voice_chat_check"/> <button label="?" name="voice_chat_help"/> <check_box label="Permitir Tele-transporte direto" name="allow_direct_teleport"/> diff --git a/indra/newview/skins/default/xui/pt/panel_script_ed.xml b/indra/newview/skins/default/xui/pt/panel_script_ed.xml index a1acb18cb4..de02aafe2f 100644 --- a/indra/newview/skins/default/xui/pt/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/pt/panel_script_ed.xml @@ -22,6 +22,8 @@ <menu label="Arquivo" name="File"> <menu_item_call label="Salvar" name="Save"/> <menu_item_call label="Reverter todas as alterações" name="Revert All Changes"/> + <menu_item_call label="Carregar do arquivo..." name="LoadFromFile"/> + <menu_item_call label="Salvar para o arquivo..." name="SaveToFile"/> </menu> <menu label="Editar" name="Edit"> <menu_item_call label="desfazer" name="Undo"/> diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml index 22853f0643..cb9a6eb757 100644 --- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml @@ -15,7 +15,7 @@ <panel.string name="buycurrencylabel"> L$ [AMT] </panel.string> - <panel name="balance_bg"> + <panel left="-410" name="balance_bg" width="200"> <text name="balance" tool_tip="Atualizar saldo de L$" value="L$20"/> <button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/> <button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life" width="80"/> diff --git a/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml b/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml index 77c552a852..7908ea5f3a 100644 --- a/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml @@ -2,47 +2,24 @@ <panel label="Coisas" name="objects panel"> <panel label="" name="sidepanel__inventory_panel"> <layout_stack name="inventory_layout_stack"> - <layout_panel name="inbox_outbox_layout_panel"> - <layout_stack name="inbox_outbox_layout_stack"> - <layout_panel name="inbox_layout_panel"> - <panel label="" name="marketplace_inbox"> - <string name="InboxLabelWithArg"> - Itens recebidos ([NUM]) - </string> - <string name="InboxLabelNoArg"> - Itens recebidos - </string> - <button label="Itens recebidos" name="inbox_btn"/> - <text name="inbox_fresh_new_count"> - [NUM] novo(s) - </text> - <panel tool_tip="Drag and drop items to your inventory to manage and use them"> - <text name="inbox_inventory_placeholder"> - Compras do marketplace serão entregues aqui. - </text> - </panel> - </panel> - </layout_panel> - <layout_panel name="outbox_layout_panel"> - <panel label="" name="marketplace_outbox"> - <string name="OutboxLabelWithArg"> - Caixa de saÃda do lojista ([NUM]) - </string> - <string name="OutboxLabelNoArg"> - Caixa de saÃda do lojista - </string> - <button label="Caixa de saÃda do lojista" name="outbox_btn"/> - <button label="" name="outbox_sync_btn" tool_tip="Enviar para a frente do meu mercado"/> - <panel> - <panel name="outbox_inventory_placeholder_panel"> - <text name="outbox_inventory_placeholder_title"> - Carregando... - </text> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> + <layout_panel name="inbox_layout_panel"> + <panel label="" name="marketplace_inbox"> + <string name="InboxLabelWithArg"> + Itens recebidos ([NUM]) + </string> + <string name="InboxLabelNoArg"> + Itens recebidos + </string> + <button label="Itens recebidos" name="inbox_btn"/> + <text name="inbox_fresh_new_count"> + [NUM] novo(s) + </text> + <panel name="inbox_inventory_placeholder_panel" tool_tip="Arraste e solte itens para o seu inventário para usá-los"> + <text name="inbox_inventory_placeholder"> + As compras do marketplace serão entregues aqui. + </text> + </panel> + </panel> </layout_panel> </layout_stack> <panel name="button_panel"> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 4babd9cc43..342a52356b 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -157,9 +157,9 @@ Para saber mais, visite as perguntas frequentes abaixo: http://secondlife.com/vi O Second Life está fechado para manutenção no momento. Somente funcionários podem acessá-lo. Consulte www.secondlife.com/status para as últimas atualizações. </string> <string name="LoginFailedPremiumOnly"> - O acesso ao Second Life está sendo restrito por alguns instantes para que todos tenham a melhor experiência possÃvel. - -Titulares de contas gratuitas não poderão acessar o Second Life para acomodar os assinantes do Second Life. + Logons do Second Life estão temporariamente restritos para garantir a melhor experiência possÃvel para os usuários no mundo virtual. + +Pessoas com contas gratuitas não poderão acessar o Second Life no momento para dar espaço para aquelas que pagaram pelo Second Life. </string> <string name="LoginFailedComputerProhibited"> O Second Life não pode ser acessado deste computador. Se você acredita que houve algum equÃvoco, contate support@secondlife.com. @@ -291,17 +291,35 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar Apenas um item único pode ser arrastado para este local </string> <string name="TooltipPrice" value="L$[AMOUNT]"/> + <string name="TooltipOutboxDragToWorld"> + Não é possÃvel fazer rez do itens em sua caixa de saÃda do lojista + </string> <string name="TooltipOutboxNoTransfer"> - Um ou mais objetos não podem ser vendidos ou transferidos para outros usuário. + Um ou mais destes objetos não podem ser vendidos ou transferidos. + </string> + <string name="TooltipOutboxNotInInventory"> + Sua caixa de saÃda do lojista aceita apenas itens direto do seu inventário </string> <string name="TooltipOutboxWorn"> - Você está usando um ou mais desses objetos. Remova-os de seu avatar e tente movê-los novamente. + Você não pode colocar os itens que está vestindo na sua caixa de saÃda do lojista + </string> + <string name="TooltipOutboxCallingCard"> + Não é possÃvel colocar cartões de visita em sua caixa de saÃda do lojista </string> <string name="TooltipOutboxFolderLevels"> - Esta pasta tem muitos nÃveis de subpastas. Reorganize as pastas internas em até 4 nÃveis no máximo (Pasta raiz contém A que contém B que contém C). + A profundidade das pastas aninhadas excede 3 + </string> + <string name="TooltipOutboxTooManyFolders"> + A contagem de subpastas na pasta de nÃvel superior excede 20 </string> <string name="TooltipOutboxTooManyObjects"> - Esta pasta contém mais de 200 objetos. Embale alguns dos itens para reduzir a contagem de objetos. + A contagem de itens na pasta de nÃvel superior excede 200 + </string> + <string name="TooltipDragOntoOwnChild"> + Não é possÃvel mover uma pasta para seu filho + </string> + <string name="TooltipDragOntoSelf"> + Não é possÃvel mover uma pasta para dentro dela mesma </string> <string name="TooltipHttpUrl"> Clique para ver a página web @@ -766,6 +784,9 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar <string name="anim_yes_head"> Sim </string> + <string name="multiple_textures"> + Múltiplo + </string> <string name="texture_loading"> Carregando... </string> @@ -922,6 +943,9 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar <string name="choose_the_directory"> Selecionar pasta </string> + <string name="script_files"> + Scripts + </string> <string name="AvatarSetNotAway"> deixar como ausente </string> @@ -1160,43 +1184,36 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar Você não possui uma cópia desta textura no seu inventário </string> <string name="InventoryInboxNoItems"> - Quando você comprar ou receber um item, ele aparecerá aqui para que você possa arrastá-lo para uma pasta em seu inventário ou excluÃ-lo caso não queira mantê-lo. + Suas compras do Marketplace aparecerão aqui. Depois, você poderá arrastá-las para seu inventário para usá-las. </string> <string name="MarketplaceURL"> - http://marketplace.[DOMAIN_NAME] + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/ </string> <string name="MarketplaceURL_CreateStore"> - http://marketplace.[DOMAIN_NAME]/create_store + http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 </string> - <string name="MarketplaceURL_LearnMore"> - http://marketplace.[DOMAIN_NAME]/learn_more - </string> - <string name="InventoryOutboxCreationErrorTitle"> - Sua Caixa de saÃda do lojista não está configurada corretamente + <string name="MarketplaceURL_Dashboard"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard </string> - <string name="InventoryOutboxCreationErrorTooltip"> - Erro de configuração na Caixa de saÃda do lojista + <string name="MarketplaceURL_Imports"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports </string> - <string name="InventoryOutboxCreationError"> - Entre em contato com o Atendimento para corrigir o problema. + <string name="MarketplaceURL_LearnMore"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more </string> <string name="InventoryOutboxNotMerchantTitle"> - Qualquer um pode vender itens no Mercado - </string> - <string name="InventoryOutboxNotMerchantTooltip"> - Torne-se um lojista! + Qualquer um pode vender itens no Mercado. </string> + <string name="InventoryOutboxNotMerchantTooltip"/> <string name="InventoryOutboxNotMerchant"> - [[MARKETPLACE_URL] O Mercado do Second Life] oferece mais de um milhão de produtos virtuais para venda, todos criados pelos residentes. Você também pode vender os itens que você cria, além de alguns itens que comprou. É fácil e a configuração é gratuita. [[LEARN_MORE_URL] Saiba mais] ou [[CREATE_STORE_URL] crie uma loja] no Mercado para começar. + Se você deseja se tornar um lojista, precisará [[MARKETPLACE_CREATE_STORE_URL] criar uma loja no Mercado]. </string> <string name="InventoryOutboxNoItemsTitle"> - Uma nova maneira de vender os itens no Mercado - </string> - <string name="InventoryOutboxNoItemsTooltip"> - Arraste e solte os itens aqui para prepará-los para venda no Mercado + Sua caixa de saÃda está vazia </string> + <string name="InventoryOutboxNoItemsTooltip"/> <string name="InventoryOutboxNoItems"> - Arraste os itens ou pastas que deseja vender para esta área. Será exibida uma cópia deles, deixando seu inventário inalterado, a menos que você arraste um item que não permita cópia. Quando estiver pronto para enviar os itens para o Mercado, clique no botão Enviar. Quando os itens tiverem sido movidos para seu Inventário de mercado, eles desaparecerão desta pasta. + Arraste as pastas para estas áreas e então clique em "Enviar para Mercado" para listar os itens para venda no [[MARKETPLACE_DASHBOARD_URL] Mercado]. </string> <string name="Marketplace Error None"> Sem erros @@ -1208,7 +1225,7 @@ Titulares de contas gratuitas não poderão acessar o Second Life para acomodar Erro: esta pasta está vazia. </string> <string name="Marketplace Error Unassociated Products"> - Erro: ocorreu uma falha ao enviar este item, pois sua conta de lojista tem muitos itens não associados a produtos. Para corrigir esse erro, faça o login no site do mercado e reduza a contagem de itens não associados. + Erro: ocorreu uma falha ao enviar este item, pois sua conta de lojista tem muitos itens não associados a produtos. Para corrigir esse erro, faça o login no site do mercado e reduza a contagem de itens não associados. </string> <string name="Marketplace Error Object Limit"> Erro: este item contém muitos objetos. Corrija esse erro unindo os objetos em caixa para reduzir a contagem total a menos de 200. @@ -3783,6 +3800,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Saved_message"> (Salvo em [LONG_TIMESTAMP]) </string> + <string name="IM_unblock_only_groups_friends"> + Para visualizar esta mensagem, você deve desmarcar "Apenas amigos e grupos podem me ligar ou enviar MIs" em Preferências/Privacidade. + </string> <string name="answered_call"> Ligação atendida </string> @@ -3971,7 +3991,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. </string> <string name="uploading_abuse_report"> Carregando... - + Denunciar abuso </string> <string name="New Shape"> @@ -4237,10 +4257,10 @@ Denunciar abuso </string> <string name="words_separator" value=","/> <string name="server_is_down"> - Aconteceu algo inesperado, apesar de termos tentador impedir isso. + Aconteceu algo inesperado, apesar de termos tentado impedir isso. - Cheque secondlifegrid.net para saber se foi detectado um problema com o serviço. - Se o problema persisitr, cheque a configuração da sua rede e firewall. + Cheque secondlifegrid.net para saber se foi detectado um problema com o serviço. + Se o problema persistir, cheque a configuração da sua rede e firewall. </string> <string name="dateTimeWeekdaysNames"> Domingo:Segunda:Terça:Quarta:Quinta:Sexta:Sábado @@ -4706,6 +4726,9 @@ Tente colocar o caminho do editor entre aspas. <string name="Command_Move_Label"> Andar/correr/voar </string> + <string name="Command_Outbox_Label"> + Caixa de saÃda do lojista + </string> <string name="Command_People_Label"> Pessoas </string> @@ -4778,6 +4801,9 @@ Tente colocar o caminho do editor entre aspas. <string name="Command_Move_Tooltip"> Movendo seu avatar </string> + <string name="Command_Outbox_Tooltip"> + Transferir itens para o seu mercado para venda + </string> <string name="Command_People_Tooltip"> Amigos, grupos e pessoas próximas </string> diff --git a/indra/newview/skins/default/xui/ru/floater_about_land.xml b/indra/newview/skins/default/xui/ru/floater_about_land.xml index 46414a530a..ee74aad5cc 100644 --- a/indra/newview/skins/default/xui/ru/floater_about_land.xml +++ b/indra/newview/skins/default/xui/ru/floater_about_land.xml @@ -306,9 +306,6 @@ <panel.string name="push_restrict_region_text"> Ðе толкать (наÑтройки региона) </panel.string> - <panel.string name="see_avs_text"> - Ðватары Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… учаÑтков могут видеть - </panel.string> <text name="allow_label"> Позволить другим жителÑм: </text> @@ -371,7 +368,7 @@ </text> <texture_picker name="snapshot_ctrl" tool_tip="Щелкните Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° изображениÑ"/> <text name="allow_label5"> - аватары на Ñтом учаÑтке и общатьÑÑ Ñ Ð½Ð¸Ð¼Ð¸ + Ðватары Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… учаÑтков могут видеть аватары на Ñтом учаÑтке и общатьÑÑ Ñ Ð½Ð¸Ð¼Ð¸ </text> <check_box label="Видны аватары" name="SeeAvatarsCheck" tool_tip="Ðватары Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… учаÑтков Ñмогут видеть аватары на Ñтом учаÑтке и общатьÑÑ Ñ Ð½Ð¸Ð¼Ð¸ в чате, а вы также Ñможете видеть их и общатьÑÑ Ñ Ð½Ð¸Ð¼Ð¸."/> <text name="landing_point"> @@ -446,20 +443,15 @@ <panel.string name="access_estate_defined"> (Определено на землевладении) </panel.string> - <panel.string name="allow_public_access"> - Разрешить общий доÑтуп ([MATURITY]) (СнÑтие приведет к Ñозданию линий запрета) - </panel.string> <panel.string name="estate_override"> ЧаÑÑ‚ÑŒ Ñтих параметров уÑтановлена на уровне Ð·ÐµÐ¼Ð»ÐµÐ²Ð»Ð°Ð´ÐµÐ½Ð¸Ñ </panel.string> - <text name="Limit access to this parcel to:"> - ДоÑтуп на Ñтот учаÑток - </text> + <check_box label="Разрешить публичный доÑтуп (ÑнÑтие флажка приведет к Ñозданию линий запрета)" name="public_access"/> <text name="Only Allow"> - Разрешить доÑтуп только жителÑм, у которых: + Разрешить доÑтуп только таким жителÑм: </text> - <check_box label="ЗапиÑана Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± оплате [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Банить нераÑпознанных жителей."/> - <check_box label="Проверка возраÑта [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Банить жителей, не прошедших проверку возраÑта. Более Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð·Ð´ÐµÑÑŒ: [SUPPORT_SITE]."/> + <check_box label="ЗарегиÑтрирована Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± оплате [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Ð”Ð»Ñ Ð´Ð¾Ñтупа к Ñтому учаÑтку у Ð¶Ð¸Ñ‚ÐµÐ»Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° быть зарегиÑтрирована Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± оплате. Более Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð·Ð´ÐµÑÑŒ: [SUPPORT_SITE]."/> + <check_box label="Подтвержден возраÑÑ‚ [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Ð”Ð»Ñ Ð´Ð¾Ñтупа к Ñтому учаÑтку житель должен подтвердить Ñвой возраÑÑ‚. Более Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð·Ð´ÐµÑÑŒ: [SUPPORT_SITE]."/> <check_box label="Разрешить доÑтуп группе: [GROUP]" name="GroupCheck" tool_tip="Группа уÑтанавливаетÑÑ Ð½Ð° оÑновной вкладке."/> <check_box label="Продать доÑтуп:" name="PassCheck" tool_tip="Разрешить временный доÑтуп к учаÑтку."/> <combo_box name="pass_combo"> diff --git a/indra/newview/skins/default/xui/ru/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/ru/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..711afc2717 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_animation_anim_preview.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Anim Preview" title="ANIMATION.ANIM"> + <text name="name_label"> + Ðазвание: + </text> + <text name="description_label"> + ОпиÑание: + </text> + <button label="Передать (L$[AMOUNT])" name="ok_btn"/> + <button label="Отмена" label_selected="Отмена" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_animation_bvh_preview.xml b/indra/newview/skins/default/xui/ru/floater_animation_bvh_preview.xml new file mode 100644 index 0000000000..8ad9d8657a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_animation_bvh_preview.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Animation Preview"> + <floater.string name="failed_to_initialize"> + Ðевозможно инициализировать движение + </floater.string> + <floater.string name="anim_too_long"> + Длина файла анимации: [LENGTH] Ñ. + +МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° анимации: [MAX_LENGTH] Ñ. + </floater.string> + <floater.string name="failed_file_read"> + Ðевозможно прочитать файл анимации. + +[STATUS] + </floater.string> + <floater.string name="E_ST_OK"> + ОК + </floater.string> + <floater.string name="E_ST_EOF"> + Преждевременный конец файла. + </floater.string> + <floater.string name="E_ST_NO_CONSTRAINT"> + Ðе могу прочитать определение ограничений. + </floater.string> + <floater.string name="E_ST_NO_FILE"> + Ðе удалоÑÑŒ открыть BVH-файл. + </floater.string> + <floater.string name="E_ST_NO_HIER"> + Ðеправильный заголовок HIERARCHY. + </floater.string> + <floater.string name="E_ST_NO_JOINT"> + Ðе удалоÑÑŒ найти ROOT или JOINT. + </floater.string> + <floater.string name="E_ST_NO_NAME"> + Ðе удалоÑÑŒ получить Ð¸Ð¼Ñ JOINT. + </floater.string> + <floater.string name="E_ST_NO_OFFSET"> + Ðе удалоÑÑŒ найти OFFSET. + </floater.string> + <floater.string name="E_ST_NO_CHANNELS"> + Ðе удалоÑÑŒ найти CHANNELS. + </floater.string> + <floater.string name="E_ST_NO_ROTATION"> + Ðе удалоÑÑŒ получить порÑдок вращениÑ. + </floater.string> + <floater.string name="E_ST_NO_AXIS"> + Ðе удалоÑÑŒ получить оÑи вращениÑ. + </floater.string> + <floater.string name="E_ST_NO_MOTION"> + Ðе удалоÑÑŒ найти MOTION. + </floater.string> + <floater.string name="E_ST_NO_FRAMES"> + Ðе удалоÑÑŒ получить количеÑтво кадров. + </floater.string> + <floater.string name="E_ST_NO_FRAME_TIME"> + Ðе удалоÑÑŒ получить Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ð´Ñ€Ð°. + </floater.string> + <floater.string name="E_ST_NO_POS"> + Ðе удалоÑÑŒ получить Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ position. + </floater.string> + <floater.string name="E_ST_NO_ROT"> + Ðе удалоÑÑŒ получить Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ rotation. + </floater.string> + <floater.string name="E_ST_NO_XLT_FILE"> + Ðе удалоÑÑŒ открыть файл перевода. + </floater.string> + <floater.string name="E_ST_NO_XLT_HEADER"> + Ðе удалоÑÑŒ прочитать заголовок перевода. + </floater.string> + <floater.string name="E_ST_NO_XLT_NAME"> + Ðе удалоÑÑŒ прочитать имена перевода. + </floater.string> + <floater.string name="E_ST_NO_XLT_IGNORE"> + Ðе удалоÑÑŒ прочитать значение перевода ignore. + </floater.string> + <floater.string name="E_ST_NO_XLT_RELATIVE"> + Ðе удалоÑÑŒ прочитать значение перевода relative. + </floater.string> + <floater.string name="E_ST_NO_XLT_OUTNAME"> + Ðе удалоÑÑŒ прочитать значение перевода outname. + </floater.string> + <floater.string name="E_ST_NO_XLT_MATRIX"> + Ðе удалоÑÑŒ прочитать матрицу перевода. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGECHILD"> + Ðе удалоÑÑŒ получить Ð¸Ð¼Ñ mergechild. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGEPARENT"> + Ðе удалоÑÑŒ получить Ð¸Ð¼Ñ mergeparent. + </floater.string> + <floater.string name="E_ST_NO_XLT_PRIORITY"> + Ðе удалоÑÑŒ получить значение priority. + </floater.string> + <floater.string name="E_ST_NO_XLT_LOOP"> + Ðе удалоÑÑŒ получить значение loop. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEIN"> + Ðе удалоÑÑŒ получить Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ easeIn. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEOUT"> + Ðе удалоÑÑŒ получить Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ easeOut. + </floater.string> + <floater.string name="E_ST_NO_XLT_HAND"> + Ðе удалоÑÑŒ получить значение hand morph. + </floater.string> + <floater.string name="E_ST_NO_XLT_EMOTE"> + Ðе удалоÑÑŒ прочитать Ð¸Ð¼Ñ emote. + </floater.string> + <floater.string name="E_ST_BAD_ROOT"> + Ðеверное Ð¸Ð¼Ñ ÐºÐ¾Ñ€Ð½ÐµÐ²Ð¾Ð³Ð¾ ÑоединениÑ, должно быть «hip». + </floater.string> + <text name="name_label"> + Ðазвание: + </text> + <text name="description_label"> + ОпиÑание: + </text> + <spinner label="Приоритет" name="priority" tool_tip="УправлÑет тем, как другие анимации могут перекрыватьÑÑ Ñтой"/> + <check_box label="Цикл" name="loop_check" tool_tip="Делает анимацию зацикленной"/> + <spinner label="Ðачало(%)" name="loop_in_point" tool_tip="УÑтанавливает точку возврата цикла"/> + <spinner label="Конец(%)" name="loop_out_point" tool_tip="УÑтанавливает точку конца цикла"/> + <text name="hand_label"> + Положение пальцев + </text> + <combo_box name="hand_pose_combo" tool_tip="Контролирует положение пальцев во Ð²Ñ€ÐµÐ¼Ñ Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ð¸"> + <combo_box.item label="Разведены" name="Spread"/> + <combo_box.item label="РаÑÑлаблены" name="Relaxed"/> + <combo_box.item label="Указывают" name="PointBoth"/> + <combo_box.item label="Сжаты в кулак" name="Fist"/> + <combo_box.item label="Левые раÑÑлаблены" name="RelaxedLeft"/> + <combo_box.item label="Левые указывают" name="PointLeft"/> + <combo_box.item label="Левые в кулак" name="FistLeft"/> + <combo_box.item label="Правые раÑÑлаблены" name="RelaxedRight"/> + <combo_box.item label="Правые указывают" name="PointRight"/> + <combo_box.item label="Правые в кулак" name="FistRight"/> + <combo_box.item label="Правые в приветÑтвии" name="SaluteRight"/> + <combo_box.item label="Печатают" name="Typing"/> + <combo_box.item label="Правые «V»" name="PeaceRight"/> + </combo_box> + <text name="emote_label"> + Выражение лица + </text> + <combo_box name="emote_combo" tool_tip="Контролирует выражение лица во Ð²Ñ€ÐµÐ¼Ñ Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ð¸"> + <item label="(нет)" name="[None]" value=""/> + <item label="Ðаааах" name="Aaaaah" value="Ðаааах"/> + <item label="БоитÑÑ" name="Afraid" value="БоитÑÑ"/> + <item label="ЗлитÑÑ" name="Angry" value="ЗлитÑÑ"/> + <item label="Широко улыбаетÑÑ" name="BigSmile" value="Широко улыбаетÑÑ"/> + <item label="Скучает" name="Bored" value="Скучает"/> + <item label="Плачет" name="Cry" value="Плачет"/> + <item label="Презирает" name="Disdain" value="Презирает"/> + <item label="СмущаетÑÑ" name="Embarrassed" value="СмущаетÑÑ"/> + <item label="ХмуритÑÑ" name="Frown" value="ХмуритÑÑ"/> + <item label="Целует" name="Kiss" value="Целует"/> + <item label="СмеетÑÑ" name="Laugh" value="СмеетÑÑ"/> + <item label="ДразнитÑÑ" name="Plllppt" value="ДразнитÑÑ"/> + <item label="Ðе ÑоглашаетÑÑ" name="Repulsed" value="Ðе ÑоглашаетÑÑ"/> + <item label="ГруÑтит" name="Sad" value="ГруÑтит"/> + <item label="Ðе понимает" name="Shrug" value="Ðе понимает"/> + <item label="УлыбаетÑÑ" name="Smile" value="УлыбаетÑÑ"/> + <item label="УдивлÑетÑÑ" name="Surprise" value="УдивлÑетÑÑ"/> + <item label="Подмигивает" name="Wink" value="Подмигивает"/> + <item label="БеÑпокоитÑÑ" name="Worry" value="БеÑпокоитÑÑ"/> + </combo_box> + <text name="preview_label"> + ПроÑмотр во Ð²Ñ€ÐµÐ¼Ñ + </text> + <combo_box name="preview_base_anim" tool_tip="ПроÑмотр вашей анимации во Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð°Ð²Ð°Ñ‚Ð°Ñ€Ð¾Ð¼ дейÑтвий."> + <item label="СтоÑние" name="Standing" value="СтоÑние"/> + <item label="Ходьба" name="Walking" value="Ходьба"/> + <item label="Сидение" name="Sitting" value="Сидение"/> + <item label="Полет" name="Flying" value="Полет"/> + </combo_box> + <spinner label="Вход (Ñек.)" name="ease_in_time" tool_tip="КоличеÑтво времени (в Ñекундах) Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в Ñтартовое положение"/> + <spinner label="Выход (Ñек.)" name="ease_out_time" tool_tip="КоличеÑтво времени (в Ñекундах) Ð´Ð»Ñ Ð²Ñ‹Ñ…Ð¾Ð´Ð° из анимации"/> + <button name="play_btn" tool_tip="Проиграть анимацию"/> + <button name="pause_btn" tool_tip="ПриоÑтановить анимацию"/> + <button name="stop_btn" tool_tip="ОÑтановить проигрывание анимации"/> + <text name="bad_animation_text"> + Ðевозможно прочитать файл анимации. + +РекомендуетÑÑ Ð¸Ñпользовать BVH-файлы, ÑкÑпортированные из Poser 4. + </text> + <button label="Передать (L$[AMOUNT])" name="ok_btn"/> + <button label="Отмена" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/ru/floater_merchant_outbox.xml new file mode 100644 index 0000000000..332fa3b82f --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_merchant_outbox.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_merchant_outbox" title="ТОРГОВЫЕ ИСХОДЯЩИЕ"> + <string name="OutboxFolderCount1"> + 1 папка + </string> + <string name="OutboxFolderCountN"> + [NUM] папки + </string> + <string name="OutboxImporting"> + Отправка папок.... + </string> + <string name="OutboxInitializing"> + ИнициализациÑ... + </string> + <panel label=""> + <panel> + <panel name="outbox_inventory_placeholder_panel"> + <text name="outbox_inventory_placeholder_title"> + Загрузка... + </text> + </panel> + </panel> + <panel> + <button label="Отправить в торговый центр" name="outbox_import_btn" tool_tip="Ð’Ñ‹Ñтавить на витрину моего магазина"/> + </panel> + </panel> +</floater> 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 5b03dd2c73..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="header_panel"> - <text name="header_text"> - Выберите файл модели - </text> - </panel> - <panel name="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="header_panel"> - <text name="header_text"> - Оптимизировать модель - </text> - </panel> - <text name="description"> - Мы оптимизировали модель Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‹ÑˆÐµÐ½Ð¸Ñ Ð±Ñ‹ÑтродейÑтвиÑ. По желанию можно выполнить дополнительную наÑтройку. - </text> - <panel name="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="header_panel"> - <text name="header_text"> - ÐаÑтроить физику - </text> - </panel> - <text name="description"> - Мы Ñоздадим форму Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ каркаÑа модели. ÐаÑтройте уровень детализации формы в ÑоответÑтвии Ñ Ñ†ÐµÐ»Ñми, Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… предназначена модель. - </text> - <panel name="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="header_panel"> - <text name="header_text"> - ПроÑмотр - </text> - </panel> - <panel name="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="header_panel"> - <text name="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_preview_animation.xml b/indra/newview/skins/default/xui/ru/floater_preview_animation.xml index a1fabedb85..22c6bc5901 100644 --- a/indra/newview/skins/default/xui/ru/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/ru/floater_preview_animation.xml @@ -6,6 +6,6 @@ <text name="desc txt"> ОпиÑание: </text> - <button label="Проиграть Ð´Ð»Ñ Ð²Ñех" label_selected="Стоп" name="Anim play btn" tool_tip="Проигрывание Ñтой анимации могут видеть другие учаÑтники"/> - <button label="Проиграть Ð´Ð»Ñ ÑебÑ" label_selected="Стоп" name="Anim audition btn" tool_tip="Проигрывание Ñтой анимации можете видеть только вы"/> + <button label="Проиграть Ð´Ð»Ñ Ð²Ñех" label_selected="Стоп" name="Inworld" tool_tip="Проигрывание Ñтой анимации могут видеть другие учаÑтники"/> + <button label="Проиграть Ð´Ð»Ñ ÑебÑ" label_selected="Стоп" name="Locally" tool_tip="Проигрывание Ñтой анимации можете видеть только вы"/> </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/ru/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..b479d5f6d6 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_test_layout_stacks.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="LAYOUTSTACK TESTS"/> diff --git a/indra/newview/skins/default/xui/ru/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/ru/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..d0bd86160e --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_test_text_vertical_aligment.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="ТЕСТИРОВÐТЬ ОКÐО"/> diff --git a/indra/newview/skins/default/xui/ru/floater_tools.xml b/indra/newview/skins/default/xui/ru/floater_tools.xml index eb9083f7fc..3d7d1198f0 100644 --- a/indra/newview/skins/default/xui/ru/floater_tools.xml +++ b/indra/newview/skins/default/xui/ru/floater_tools.xml @@ -1,5 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="toolbox floater" short_title="ИÐСТРУМЕÐТЫ ДЛЯ СТРОИТЕЛЬСТВÐ"> + <floater.string name="grid_screen_text"> + Ðкран + </floater.string> + <floater.string name="grid_local_text"> + Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ + </floater.string> + <floater.string name="grid_world_text"> + ÐœÐ¸Ñ€Ð¾Ð²Ð°Ñ + </floater.string> + <floater.string name="grid_reference_text"> + Точка отÑчета + </floater.string> + <floater.string name="grid_attachment_text"> + ПриÑоединение + </floater.string> <floater.string name="status_rotate"> ПеретÑгивайте цветные полоÑÑ‹ Ð´Ð»Ñ Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð° </floater.string> @@ -63,7 +78,12 @@ </text> <check_box initial_value="иÑтина" label="РаÑÑ‚Ñгивать текÑтуры" name="checkbox stretch textures"/> <check_box initial_value="иÑтина" label="ПривÑзка" name="checkbox snap to grid"/> - <button label="Параметры..." name="Options..." tool_tip="Дополнительные параметры Ñетки"/> + <combo_box name="combobox grid mode" tool_tip="Выберите тип линейки Ñетки Ð´Ð»Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°"> + <combo_box.item label="МироваÑ" name="World"/> + <combo_box.item label="ЛокальнаÑ" name="Local"/> + <combo_box.item label="Точка отÑчета" name="Reference"/> + </combo_box> + <button label="" name="Options..." tool_tip="Дополнительные параметры Ñетки"/> <button name="ToolCube" tool_tip="Куб"/> <button name="ToolPrism" tool_tip="Призма"/> <button name="ToolPyramid" tool_tip="Пирамида"/> diff --git a/indra/newview/skins/default/xui/ru/floater_voice_effect.xml b/indra/newview/skins/default/xui/ru/floater_voice_effect.xml index d4bf615fe4..1eb8a94d7a 100644 --- a/indra/newview/skins/default/xui/ru/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/ru/floater_voice_effect.xml @@ -42,13 +42,16 @@ <string name="effect_Demon"> Demon </string> + <string name="effect_Female Elf"> + Ð¤ÐµÑ + </string> <string name="effect_Flirty"> Flirty </string> <string name="effect_Foxy"> Foxy </string> - <string name="effect_Halloween_2010_Bonus"> + <string name="effect_Halloween 2010 Bonus"> БонуÑ_за_Ð¥Ñллоуин_2010 </string> <string name="effect_Helium"> @@ -57,9 +60,18 @@ <string name="effect_Husky"> Husky </string> + <string name="effect_Husky Whisper"> + Хриплый шепот + </string> <string name="effect_Intercom"> ВнутреннÑÑ ÑвÑзь </string> + <string name="effect_Julia"> + Julia + </string> + <string name="effect_Lo Lilt"> + Ðапев + </string> <string name="effect_Macho"> Macho </string> @@ -69,6 +81,9 @@ <string name="effect_Mini"> Mini </string> + <string name="effect_Model"> + Модель + </string> <string name="effect_Nano"> Nano </string> @@ -90,6 +105,9 @@ <string name="effect_Roxanne"> Roxanne </string> + <string name="effect_Rumble"> + Урчание + </string> <string name="effect_Sabrina"> Sabrina </string> @@ -102,6 +120,9 @@ <string name="effect_Shorty"> Shorty </string> + <string name="effect_Smaller"> + Меньше + </string> <string name="effect_Sneaky"> Sneaky </string> diff --git a/indra/newview/skins/default/xui/ru/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/ru/menu_inspect_object_gear.xml index a72b2bef23..30953e830b 100644 --- a/indra/newview/skins/default/xui/ru/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/ru/menu_inspect_object_gear.xml @@ -12,6 +12,7 @@ <menu_item_call label="Добавить" name="add"/> <menu_item_call label="ПожаловатьÑÑ" name="report"/> <menu_item_call label="Заблокировать" name="block"/> + <menu_item_call label="Разблокировать" name="unblock"/> <menu_item_call label="Приблизить" name="zoom_in"/> <menu_item_call label="Удалить" name="remove"/> <menu_item_call label="Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ" name="more_info"/> diff --git a/indra/newview/skins/default/xui/ru/menu_inventory.xml b/indra/newview/skins/default/xui/ru/menu_inventory.xml index 4eeb1e46c2..49f7281b4e 100644 --- a/indra/newview/skins/default/xui/ru/menu_inventory.xml +++ b/indra/newview/skins/default/xui/ru/menu_inventory.xml @@ -59,6 +59,7 @@ <menu_item_call label="СвойÑтва" name="Properties"/> <menu_item_call label="Переименовать" name="Rename"/> <menu_item_call label="Копировать UUID актива" name="Copy Asset UUID"/> + <menu_item_call label="Вырезать" name="Cut"/> <menu_item_call label="Копировать" name="Copy"/> <menu_item_call label="Ð’Ñтавить" name="Paste"/> <menu_item_call label="Ð’Ñтавить как ÑÑылку" name="Paste As Link"/> @@ -84,6 +85,6 @@ <menu_item_call label="Добавить" name="Wearable Add"/> <menu_item_call label="СнÑÑ‚ÑŒ" name="Take Off"/> <menu_item_call label="Копировать в «Торговые иÑходÑщие»" name="Merchant Copy"/> - <menu_item_call label="ПеремеÑтить в «Торговые иÑходÑщие»" name="Merchant Move"/> + <menu_item_call label="Отправить в торговый центр" name="Marketplace Send"/> <menu_item_call label="- нет дейÑтвий -" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/ru/menu_login.xml b/indra/newview/skins/default/xui/ru/menu_login.xml index aa3570f176..93a5ffbb25 100644 --- a/indra/newview/skins/default/xui/ru/menu_login.xml +++ b/indra/newview/skins/default/xui/ru/menu_login.xml @@ -17,8 +17,8 @@ <menu_item_call label="Задать размер окна..." name="Set Window Size..."/> <menu_item_call label="Показать лицензионное Ñоглашение" name="TOS"/> <menu_item_call label="Показать Ñообщение об ошибке" name="Critical"/> - <menu_item_call label="Проверка медиабраузера" name="Web Browser Test"/> <menu_item_call label="ТеÑÑ‚ отладки плавающего окна Ñ Ð²ÐµÐ±-контентом" name="Web Content Floater Debug Test"/> + <menu label="Уровень журнала" name="Set Logging Level"/> <menu_item_check label="Выбор Ñетки" name="Show Grid Picker"/> <menu_item_call label="КонÑоль уведомлений" name="Show Notifications Console"/> </menu> diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml index 93d0166568..0699314d97 100644 --- a/indra/newview/skins/default/xui/ru/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml @@ -14,14 +14,14 @@ <menu_item_check label="Полет" name="Fly"/> <menu_item_check label="Ð’Ñегда бегать" name="Always Run"/> <menu_item_call label="ОÑтановить анимацию" name="Stop Animating My Avatar"/> + <menu_item_call label="Ходьба / бег / полет..." name="Walk / run / fly"/> </menu> <menu label="СтатуÑ" name="Status"> <menu_item_call label="Ðет на меÑте" name="Set Away"/> <menu_item_call label="Ðе беÑпокоить" name="Set Busy"/> </menu> - <menu_item_call label="Ð—Ð°Ð¿Ñ€Ð¾Ñ ÑтатуÑа админиÑтратора" name="Request Admin Options"/> - <menu_item_call label="Выход из ÑтатуÑа админиÑтратора" name="Leave Admin Options"/> - <menu_item_call label="Купить L$" name="Buy and Sell L$"/> + <menu_item_call label="Купить L$..." name="Buy and Sell L$"/> + <menu_item_call label="Торговые иÑходÑщие..." name="MerchantOutbox"/> <menu_item_call label="Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ аккаунта..." name="Manage My Account"/> <menu_item_call label="ÐаÑтройки..." name="Preferences"/> <menu_item_call label="Кнопки панели инÑтрументов..." name="Toolbars"/> @@ -61,7 +61,7 @@ <menu_item_check label="СвойÑтва учаÑтка" name="Parcel Properties"/> <menu_item_check label="Меню «Дополнительно»" name="Show Advanced Menu"/> </menu> - <menu label="Солнце" name="Environment Settings"> + <menu label="Солнце" name="Sun"> <menu_item_call label="ВоÑход" name="Sunrise"/> <menu_item_call label="Полдень" name="Noon"/> <menu_item_call label="Закат" name="Sunset"/> @@ -176,22 +176,22 @@ <menu_item_check label="Показывать прицел при обзоре мышью" name="ShowCrosshairs"/> </menu> <menu label="Типы визуализации" name="Rendering Types"> - <menu_item_check label="ОбычнаÑ" name="Simple"/> - <menu_item_check label="Ðльфа" name="Alpha"/> - <menu_item_check label="Дерево" name="Tree"/> - <menu_item_check label="Ðватары" name="Character"/> - <menu_item_check label="ИÑправление поверхноÑти" name="Surface Patch"/> - <menu_item_check label="Ðебо" name="Sky"/> - <menu_item_check label="Вода" name="Water"/> - <menu_item_check label="ЗемлÑ" name="Ground"/> - <menu_item_check label="Объем" name="Volume"/> - <menu_item_check label="Трава" name="Grass"/> - <menu_item_check label="Облака" name="Clouds"/> - <menu_item_check label="ЧаÑтицы" name="Particles"/> - <menu_item_check label="Рельефное" name="Bump"/> + <menu_item_check label="ПроÑтой" name="Rendering Type Simple"/> + <menu_item_check label="Ðльфа" name="Rendering Type Alpha"/> + <menu_item_check label="Дерево" name="Rendering Type Tree"/> + <menu_item_check label="Ðватары" name="Rendering Type Character"/> + <menu_item_check label="ИÑправление поверхноÑти" name="Rendering Type Surface Patch"/> + <menu_item_check label="Ðебо" name="Rendering Type Sky"/> + <menu_item_check label="Вода" name="Rendering Type Water"/> + <menu_item_check label="ЗемлÑ" name="Rendering Type Ground"/> + <menu_item_check label="Объем" name="Rendering Type Volume"/> + <menu_item_check label="Трава" name="Rendering Type Grass"/> + <menu_item_check label="Облака" name="Rendering Type Clouds"/> + <menu_item_check label="ЧаÑтицы" name="Rendering Type Particles"/> + <menu_item_check label="Рельефное" name="Rendering Type Bump"/> </menu> <menu label="Функции визуализации" name="Rendering Features"> - <menu_item_check label="Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ" name="UI"/> + <menu_item_check label="Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ" name="ToggleUI"/> <menu_item_check label="Выбрано" name="Selected"/> <menu_item_check label="Выделено" name="Highlighted"/> <menu_item_check label="ДинамичеÑкие текÑтуры" name="Dynamic Textures"/> @@ -205,8 +205,6 @@ <menu_item_check label="Сглаживание мышью" name="Mouse Smoothing"/> <menu_item_call label="ОÑвободить клавиши" name="Release Keys"/> <menu label="ГорÑчие клавиши" name="Shortcuts"> - <menu_item_call label="Изображение (L$[COST])..." name="Upload Image"/> - <menu_item_check label="ПоиÑк" name="Search"/> <menu_item_check label="Показать меню «Дополнительно» - Ñтарое Ñочетание клавиш" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Закрыть окно" name="Close Window"/> <menu_item_call label="Закрыть вÑе окна" name="Close All Windows"/> @@ -215,13 +213,6 @@ <menu_item_check label="Обзор джойÑтиком" name="Joystick Flycam"/> <menu_item_call label="Ð¡Ð±Ñ€Ð¾Ñ Ð¾Ð±Ð·Ð¾Ñ€Ð°" name="Reset View"/> <menu_item_call label="Смотреть на поÑледнего говорившего" name="Look at Last Chatter"/> - <menu label="Выбрать инÑтрументы" name="Select Tool"> - <menu_item_call label="ФокуÑ" name="Focus"/> - <menu_item_call label="Перемещение" name="Move"/> - <menu_item_call label="Редактирование" name="Edit"/> - <menu_item_call label="Создание" name="Create"/> - <menu_item_call label="ЗемлÑ" name="Land"/> - </menu> <menu_item_call label="Приблизить" name="Zoom In"/> <menu_item_call label="Стандартный маÑштаб" name="Zoom Default"/> <menu_item_call label="Отодвинуть" name="Zoom Out"/> @@ -294,6 +285,7 @@ <menu_item_check label="Лучи" name="Raycast"/> <menu_item_check label="ÐÐ°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ‚Ñ€Ð°" name="Wind Vectors"/> <menu_item_check label="СложноÑÑ‚ÑŒ визуализации" name="rendercomplexity"/> + <menu_item_check label="Байты приÑоединениÑ" name="attachment bytes"/> <menu_item_check label="Лепка" name="Sculpt"/> </menu> <menu label="ВизуализациÑ" name="Rendering"> @@ -335,9 +327,8 @@ <menu_item_call label="Ðачать запиÑÑŒ" name="Start Record"/> <menu_item_call label="ОÑтановить запиÑÑŒ" name="Stop Record"/> </menu> - <menu label="Мир" name="World"> + <menu label="Мир" name="DevelopWorld"> <menu_item_check label="Перекрытие Ñолнца в ÑимулÑторе" name="Sim Sun Override"/> - <menu_item_check label="Мигающий маÑк" name="Cheesy Beacon"/> <menu_item_check label="ÐÐµÐ¸Ð·Ð¼ÐµÐ½Ð½Ð°Ñ Ð¿Ð¾Ð³Ð¾Ð´Ð°" name="Fixed Weather"/> <menu_item_call label="Вывод кÑша региональных объектов" name="Dump Region Object Cache"/> </menu> @@ -369,11 +360,11 @@ </menu> <menu label="Ðватар" name="Character"> <menu label="Захват запеченных текÑтур" name="Grab Baked Texture"> - <menu_item_call label="Радужка" name="Iris"/> - <menu_item_call label="Голова" name="Head"/> - <menu_item_call label="ВерхнÑÑ Ñ‡Ð°ÑÑ‚ÑŒ тела" name="Upper Body"/> - <menu_item_call label="ÐижнÑÑ Ñ‡Ð°ÑÑ‚ÑŒ тела" name="Lower Body"/> - <menu_item_call label="Юбка" name="Skirt"/> + <menu_item_call label="Радужка" name="Grab Iris"/> + <menu_item_call label="Голова" name="Grab Head"/> + <menu_item_call label="ВерхнÑÑ Ñ‡Ð°ÑÑ‚ÑŒ тела" name="Grab Upper Body"/> + <menu_item_call label="ÐижнÑÑ Ñ‡Ð°ÑÑ‚ÑŒ тела" name="Grab Lower Body"/> + <menu_item_call label="Юбка" name="Grab Skirt"/> </menu> <menu label="Проверка перÑонажа" name="Character Tests"> <menu_item_call label="Внешний вид в XML" name="Appearance To XML"/> @@ -401,16 +392,24 @@ <menu_item_check label="ТекÑтуры HTTP" name="HTTP Textures"/> <menu_item_check label="Инвентарь HTTP" name="HTTP Inventory"/> <menu_item_call label="Сжатие изображений" name="Compress Images"/> + <menu_item_call label="Включить Visual Leak Detector" name="Enable Visual Leak Detector"/> <menu_item_check label="Вывод минидампа при отладке" name="Output Debug Minidump"/> <menu_item_check label="Окно конÑоли при Ñледующем запуÑке" name="Console Window"/> + <menu label="Уровень журнала" name="Set Logging Level"> + <menu_item_check label="Отладка" name="Debug"/> + <menu_item_check label="ИнформациÑ" name="Info"/> + <menu_item_check label="Предупреждение" name="Warning"/> + <menu_item_check label="Ошибка" name="Error"/> + <menu_item_check label="Ðет" name="None"/> + </menu> <menu_item_call label="Ð—Ð°Ð¿Ñ€Ð¾Ñ ÑтатуÑа админиÑтратора" name="Request Admin Options"/> <menu_item_call label="Выход из ÑтатуÑа админиÑтратора" name="Leave Admin Options"/> <menu_item_check label="Показать меню админиÑтратора" name="View Admin Options"/> </menu> <menu label="ÐдминиÑтратор" name="Admin"> - <menu label="Object"> - <menu_item_call label="ВзÑÑ‚ÑŒ копию" name="Take Copy"/> - <menu_item_call label="Ðазначить ÑÐµÐ±Ñ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†ÐµÐ¼" name="Force Owner To Me"/> + <menu label="Объект" name="AdminObject"> + <menu_item_call label="Сделать копию" name="Admin Take Copy"/> + <menu_item_call label="Ðазначить Ð¼ÐµÐ½Ñ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†ÐµÐ¼" name="Force Owner To Me"/> <menu_item_call label="Ðазначить полноправным владельцем" name="Force Owner Permissive"/> <menu_item_call label="Удалить" name="Delete"/> <menu_item_call label="Ðа меÑте" name="Lock"/> @@ -445,7 +444,7 @@ <menu_item_call label="Физика" name="Physics"/> <menu_item_call label="Ð’ÑÑ Ð¾Ð´ÐµÐ¶Ð´Ð°" name="All Clothes"/> </menu> - <menu label="Справка" name="Help"> + <menu label="Справка" name="DeprecatedHelp"> <menu_item_call label="Официальный блог Linden" name="Official Linden Blog"/> <menu_item_call label="Портал Ñкриптов" name="Scripting Portal"/> <menu label="Сообщение об ошибке" name="Bug Reporting"> diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml index 04f2f6b486..b4692385d1 100644 --- a/indra/newview/skins/default/xui/ru/notifications.xml +++ b/indra/newview/skins/default/xui/ru/notifications.xml @@ -86,17 +86,38 @@ <usetemplate canceltext="Отмена" name="yesnocancelbuttons" notext="Ðе ÑохранÑÑ‚ÑŒ" yestext="Сохранить"/> </notification> <notification name="ConfirmNoCopyToOutbox"> - У Ð²Ð°Ñ Ð½ÐµÑ‚ прав Ð´Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтого Ñлемента в иÑходÑщую папку магазина. Ð’Ñ‹ дейÑтвительно хотите перемеÑтить Ñледующий Ñлемент? - [ITEM_NAME] - <usetemplate name="okcancelbuttons" notext="Ðет" yestext="Да"/> + У Ð²Ð°Ñ Ð½ÐµÑ‚ прав на копирование Ñтих предметов в папку «Торговые иÑходÑщие». ПеремеÑтите их или оÑтавьте здеÑÑŒ. + <usetemplate name="okcancelbuttons" notext="Ðе перемещать предмет(Ñ‹)" yestext="ПеремеÑтить предмет(Ñ‹)"/> + </notification> + <notification name="OutboxFolderCreated"> + Ð”Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ предмета, перенеÑенного на верхний уровень папки «Торговые иÑходÑщие», Ñоздана Ð½Ð¾Ð²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°. + <usetemplate ignoretext="Ð’ папке «Торговые иÑходÑщие» Ñоздана Ð½Ð¾Ð²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°" name="okignore" yestext="OK"/> + </notification> + <notification name="OutboxImportComplete"> + УÑпешно + +Ð’Ñе папки уÑпешно отправлены в торговый центр. + <usetemplate ignoretext="Ð’Ñе папки отправлены в торговый центр" name="okignore" yestext="OK"/> + </notification> + <notification name="OutboxImportHadErrors"> + Ðекоторые папки не перенеÑены + +Ошибки при отправке некоторых папок в торговый центр. Ðти папки оÑталиÑÑŒ в вашей папке «Торговые иÑходÑщие». + +Подробнее Ñм. в [[MARKETPLACE_IMPORTS_URL] журнале ошибок]. + <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="OutboxUploadComplete"> - Передача магазина завершена. - <usetemplate name="okbutton" yestext="Ура!"/> + <notification name="OutboxImportFailed"> + Ошибка при передаче + +Папки не отправлены в торговый центр из-за ошибки ÑиÑтемы или Ñети. Повторите попытку позже. + <usetemplate name="okbutton" yestext="OK"/> </notification> - <notification name="OutboxUploadHadErrors"> - Передача магазина выполнена Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°Ð¼Ð¸! УÑтраните проблемы в иÑходÑщей папке и повторите передачу. СпаÑибо! - <usetemplate name="okbutton" yestext="Бу-у-у!"/> + <notification name="OutboxInitFailed"> + Ошибка инициализации торгового центра + +Ðе удалоÑÑŒ инициализировать торговый центр из-за ошибки ÑиÑтемы или Ñети. Повторите попытку позже. + <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="CompileQueueSaveText"> Ошибка при передаче текÑта Ñкрипта по Ñледующей причине: [REASON]. Повторите попытку позже. @@ -649,7 +670,7 @@ Ðевозможно Ñоздать выходной файл: [FILE] </notification> <notification name="DoNotSupportBulkAnimationUpload"> - [APP_NAME] пока не поддерживает маÑÑовую передачу файлов анимации. + [APP_NAME] пока не поддерживает маÑÑовую передачу файлов анимации формата BVH. </notification> <notification name="CannotUploadReason"> Ðевозможно передать [FILE] по Ñледующей причине: [REASON] @@ -1436,7 +1457,7 @@ http://secondlife.com/download. <usetemplate ignoretext="Подтверждать перед возвратом объектов владельцам" name="okcancelignore" notext="Отмена" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Ð’Ñ‹ ÑвлÑетеÑÑŒ учаÑтником группы <nolink>[GROUP]</nolink>. + Ð’Ñ‹ ÑÐµÐ¹Ñ‡Ð°Ñ Ð²Ñ…Ð¾Ð´Ð¸Ñ‚Ðµ в группу <nolink>[GROUP]</nolink>. Хотите покинуть группу? <usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/> </notification> @@ -2609,16 +2630,16 @@ http://secondlife.com/download. [NAME] – «<nolink>[TITLE]</nolink>» [MESSAGE] <form name="form"> - <button name="Mute" text="Блокировать"/> - <button name="Ignore" text="Игнорировать"/> + <button name="Client_Side_Mute" text="Заблокировать"/> + <button name="Client_Side_Ignore" text="Игнорировать"/> </form> </notification> <notification name="ScriptDialogGroup"> [GROUPNAME] – «<nolink>[TITLE]</nolink>» [MESSAGE] <form name="form"> - <button name="Mute" text="Блокировать"/> - <button name="Ignore" text="Игнорировать"/> + <button name="Client_Side_Mute" text="Заблокировать"/> + <button name="Client_Side_Ignore" text="Игнорировать"/> </form> </notification> <notification name="BuyLindenDollarSuccess"> @@ -2816,6 +2837,18 @@ http://secondlife.com/download. [RESIDENTS] <usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/> </notification> + <notification name="ShareFolderConfirmation"> + Раздать можно только одну папку за раз. + +Ð’Ñ‹ дейÑтвительно хотите поделитьÑÑ Ð¿Ñ€ÐµÐ´Ð¼ÐµÑ‚Ð°Ð¼Ð¸: + +<nolink>[ITEMS]</nolink> + +Со Ñледующими жителÑми: + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="Отмена" yestext="ОК"/> + </notification> <notification name="ItemsShared"> Предметы уÑпешно розданы. </notification> diff --git a/indra/newview/skins/default/xui/ru/panel_nearby_chat.xml b/indra/newview/skins/default/xui/ru/panel_nearby_chat.xml index 8e3aac38d2..a8fdfde1c4 100644 --- a/indra/newview/skins/default/xui/ru/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/ru/panel_nearby_chat.xml @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="nearby_chat"> - <check_box label="Переводить чат" name="translate_chat_checkbox"/> + <layout_stack name="stack"> + <layout_panel name="translate_chat_checkbox_lp"> + <check_box label="Переводить чат" name="translate_chat_checkbox"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_region_estate.xml b/indra/newview/skins/default/xui/ru/panel_region_estate.xml index 27ec10b323..93b21704bc 100644 --- a/indra/newview/skins/default/xui/ru/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/ru/panel_region_estate.xml @@ -20,10 +20,10 @@ <slider label="Фаза" name="sun_hour_slider"/> <check_box label="Разрешить общий доÑтуп" name="externally_visible_check"/> <text name="Only Allow"> - Разрешить доÑтуп только аккаунтам Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸ÐµÐ¼: + Разрешить доÑтуп только таким жителÑм: </text> - <check_box label="Информации об оплате в файле" name="limit_payment" tool_tip="Банить нераÑпознанных жителей"/> - <check_box label="Проверка возраÑта" name="limit_age_verified" tool_tip="Банить жителей, не прошедших проверку возраÑта. Более Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð·Ð´ÐµÑÑŒ: [SUPPORT_SITE]."/> + <check_box label="ЗарегиÑтрирована Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± оплате" name="limit_payment" tool_tip="Ð”Ð»Ñ Ð´Ð¾Ñтупа к Ñтому землевладению у Ð¶Ð¸Ñ‚ÐµÐ»Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° быть зарегиÑтрирована Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± оплате. Более Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð·Ð´ÐµÑÑŒ: [SUPPORT_SITE]."/> + <check_box label="Подтвержден возраÑÑ‚" name="limit_age_verified" tool_tip="Ð”Ð»Ñ Ð´Ð¾Ñтупа к Ñтому землевладению житель должен подтвердить Ñвой возраÑÑ‚. Более Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð·Ð´ÐµÑÑŒ: [SUPPORT_SITE]."/> <check_box label="Разрешить голоÑовое общение" name="voice_chat_check"/> <check_box label="Разрешить прÑмой телепорт" name="allow_direct_teleport"/> <button label="Применить" name="apply_btn"/> diff --git a/indra/newview/skins/default/xui/ru/panel_script_ed.xml b/indra/newview/skins/default/xui/ru/panel_script_ed.xml index 1a9c512147..05ccaeb54b 100644 --- a/indra/newview/skins/default/xui/ru/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/ru/panel_script_ed.xml @@ -22,6 +22,8 @@ <menu label="Файл" name="File"> <menu_item_call label="Сохранить" name="Save"/> <menu_item_call label="Отменить вÑе изменениÑ" name="Revert All Changes"/> + <menu_item_call label="Загрузить из файла..." name="LoadFromFile"/> + <menu_item_call label="Сохранить в файл..." name="SaveToFile"/> </menu> <menu label="Изменить" name="Edit"> <menu_item_call label="Отменить" name="Undo"/> diff --git a/indra/newview/skins/default/xui/ru/panel_status_bar.xml b/indra/newview/skins/default/xui/ru/panel_status_bar.xml index babe5811ac..9c84ff1fd8 100644 --- a/indra/newview/skins/default/xui/ru/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ru/panel_status_bar.xml @@ -15,7 +15,7 @@ <panel.string name="buycurrencylabel"> L$ [AMT] </panel.string> - <panel name="balance_bg"> + <panel left="-450" name="balance_bg" width="240"> <text name="balance" tool_tip="Щелкните Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ баланÑа L$" value="L$20"/> <button label="Купить L$" name="buyL" tool_tip="Щелкните Ð´Ð»Ñ Ð¿Ð¾ÐºÑƒÐ¿ÐºÐ¸ L$"/> <button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life" width="121"/> diff --git a/indra/newview/skins/default/xui/ru/sidepanel_inventory.xml b/indra/newview/skins/default/xui/ru/sidepanel_inventory.xml index a4150f6e2f..c106c2de79 100644 --- a/indra/newview/skins/default/xui/ru/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/ru/sidepanel_inventory.xml @@ -2,47 +2,24 @@ <panel label="Вещи" name="objects panel"> <panel label="" name="sidepanel__inventory_panel"> <layout_stack name="inventory_layout_stack"> - <layout_panel name="inbox_outbox_layout_panel"> - <layout_stack name="inbox_outbox_layout_stack"> - <layout_panel name="inbox_layout_panel"> - <panel label="" name="marketplace_inbox"> - <string name="InboxLabelWithArg"> - Полученные вещи ([NUM]) - </string> - <string name="InboxLabelNoArg"> - Полученные вещи - </string> - <button label="Полученные вещи" name="inbox_btn"/> - <text name="inbox_fresh_new_count"> - Ðовых: [NUM] - </text> - <panel tool_tip="Drag and drop items to your inventory to manage and use them"> - <text name="inbox_inventory_placeholder"> - Покупки из торгового центра будут доÑтавлены Ñюда. - </text> - </panel> - </panel> - </layout_panel> - <layout_panel name="outbox_layout_panel"> - <panel label="" name="marketplace_outbox"> - <string name="OutboxLabelWithArg"> - Торговые иÑходÑщие ([NUM]) - </string> - <string name="OutboxLabelNoArg"> - Торговые иÑходÑщие - </string> - <button label="Торговые иÑходÑщие" name="outbox_btn"/> - <button label="" name="outbox_sync_btn" tool_tip="Ð’Ñ‹Ñтавить на витрину моего магазина"/> - <panel> - <panel name="outbox_inventory_placeholder_panel"> - <text name="outbox_inventory_placeholder_title"> - Загрузка... - </text> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> + <layout_panel name="inbox_layout_panel"> + <panel label="" name="marketplace_inbox"> + <string name="InboxLabelWithArg"> + Полученные вещи ([NUM]) + </string> + <string name="InboxLabelNoArg"> + Полученные вещи + </string> + <button label="Полученные вещи" name="inbox_btn"/> + <text name="inbox_fresh_new_count"> + Ðовых: [NUM] + </text> + <panel name="inbox_inventory_placeholder_panel" tool_tip="Перетащите вещи в ваш инвентарь Ð´Ð»Ñ Ð¸Ñ… иÑпользованиÑ"> + <text name="inbox_inventory_placeholder"> + Покупки из торгового центра будут доÑтавлены Ñюда. + </text> + </panel> + </panel> </layout_panel> </layout_stack> <panel name="button_panel"> diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 6d954139ff..8dbc4f092d 100644 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -180,8 +180,8 @@ http://secondlife.com/viewer-access-faq Обновление ÑоÑтоÑÐ½Ð¸Ñ Ñм. на веб-Ñтранице www.secondlife.com/status. </string> <string name="LoginFailedPremiumOnly"> - Вход в Second Life временно ограничен, чтобы обеÑпечить наилучшее времÑпровождение в игровом мире. - + Вход в Second Life временно ограничен, чтобы Ñохранить наивыÑшее качеÑтво игрового мира Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ… пользователей. + Ð’ Ñто Ð²Ñ€ÐµÐ¼Ñ Ñƒ пользователей Ñ Ð±ÐµÑплатными аккаунтами не будет доÑтупа к Second Life, чтобы у тех, кто заплатил, было больше меÑта. </string> <string name="LoginFailedComputerProhibited"> @@ -339,17 +339,35 @@ support@secondlife.com. Сюда можно перетащить только одну вещь </string> <string name="TooltipPrice" value="L$[AMOUNT]:"/> + <string name="TooltipOutboxDragToWorld"> + ÐÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð»Ð¾Ð¶Ð¸Ñ‚ÑŒ предметы из папке «Торговые иÑходÑщие» + </string> <string name="TooltipOutboxNoTransfer"> - ЧаÑÑ‚ÑŒ Ñтих объектов Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¾Ð´Ð°Ñ‚ÑŒ, или они переданы другому пользователю. + ЧаÑÑ‚ÑŒ Ñтих объектов Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¾Ð´Ð°Ñ‚ÑŒ или передать. + </string> + <string name="TooltipOutboxNotInInventory"> + Ваша папка «Торговые иÑходÑщие» может получать вещи только непоÑредÑтвенно из вашего Ð¸Ð½Ð²ÐµÐ½Ñ‚Ð°Ñ€Ñ </string> <string name="TooltipOutboxWorn"> - ЧаÑÑ‚ÑŒ Ñтих объектов на ваÑ. Снимите их Ñо Ñвоего аватара и попробуйте перемеÑтить их еще раз. + ÐоÑимые предметы Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ð¾Ð¼ÐµÑтить в папку «Торговые иÑходÑщие» + </string> + <string name="TooltipOutboxCallingCard"> + Визитки Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ð¾Ð¼ÐµÑтить в папку «Торговые иÑходÑщие» </string> <string name="TooltipOutboxFolderLevels"> - Ð’ Ñтой папке Ñлишком много уровней вложенных папок. Измените Ñтруктуру вложенных папок, ограничив ее глубину 4 уровнÑми (ÐºÐ¾Ñ€Ð½ÐµÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°, вложенные папки ÑƒÑ€Ð¾Ð²Ð½Ñ Ð, вложенные в них папки ÑƒÑ€Ð¾Ð²Ð½Ñ Ð‘, вложенные в них папки ÑƒÑ€Ð¾Ð²Ð½Ñ Ð’). + Глубина Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¿Ð¾Ðº превышает 3 + </string> + <string name="TooltipOutboxTooManyFolders"> + Ð’ папке верхнего ÑƒÑ€Ð¾Ð²Ð½Ñ Ð±Ð¾Ð»ÐµÐµ 20 подпапок </string> <string name="TooltipOutboxTooManyObjects"> - Ðта папка Ñодержит более 200 объектов. Сложите некоторые вещи в коробки, чтобы уменьшить чиÑло объектов. + Ð’ папке верхнего ÑƒÑ€Ð¾Ð²Ð½Ñ Ð±Ð¾Ð»ÐµÐµ 200 предметов + </string> + <string name="TooltipDragOntoOwnChild"> + Папку Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑтить в ее подпапку + </string> + <string name="TooltipDragOntoSelf"> + Папку Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑтить Ñаму в ÑÐµÐ±Ñ </string> <string name="TooltipHttpUrl"> Щелкните, чтобы проÑмотреть Ñту веб-Ñтраницу @@ -814,6 +832,9 @@ support@secondlife.com. <string name="anim_yes_head"> СоглаÑие </string> + <string name="multiple_textures"> + ÐеÑколько + </string> <string name="texture_loading"> Загрузка... </string> @@ -973,6 +994,9 @@ support@secondlife.com. <string name="choose_the_directory"> Выбрать каталог </string> + <string name="script_files"> + Скрипты + </string> <string name="AvatarSetNotAway"> Ðа меÑте </string> @@ -1211,43 +1235,36 @@ support@secondlife.com. Ð’ вашем инвентаре нет копии Ñтой текÑтуры </string> <string name="InventoryInboxNoItems"> - ЕÑли вы купите или как-то иначе получите предмет, он поÑвитÑÑ Ð·Ð´ÐµÑÑŒ. Его можно будет перетащить в папку вашего Ð¸Ð½Ð²ÐµÐ½Ñ‚Ð°Ñ€Ñ Ð¸Ð»Ð¸ удалить, еÑли он больше не нужен. + ЗдеÑÑŒ будут показаны ваши покупки из торгового центра. Их можно будет перетащить в ваш инвентарь Ð´Ð»Ñ Ð¸ÑпользованиÑ. </string> <string name="MarketplaceURL"> - http://marketplace.[DOMAIN_NAME] + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/ </string> <string name="MarketplaceURL_CreateStore"> - http://marketplace.[DOMAIN_NAME]/create_store + http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 </string> - <string name="MarketplaceURL_LearnMore"> - http://marketplace.[DOMAIN_NAME]/learn_more - </string> - <string name="InventoryOutboxCreationErrorTitle"> - Папка «Торговые иÑходÑщие» наÑтроена неправильно + <string name="MarketplaceURL_Dashboard"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard </string> - <string name="InventoryOutboxCreationErrorTooltip"> - Ошибка конфигурации папки «Торговые иÑходÑщие» + <string name="MarketplaceURL_Imports"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports </string> - <string name="InventoryOutboxCreationError"> - Чтобы иÑправить Ñту проблему, обратитеÑÑŒ в Ñлужбу поддержки. + <string name="MarketplaceURL_LearnMore"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more </string> <string name="InventoryOutboxNotMerchantTitle"> - Продавать вещи в торговом центре может кто угодно - </string> - <string name="InventoryOutboxNotMerchantTooltip"> - Станьте торговцем! + Продавать вещи в торговом центре может кто угодно. </string> + <string name="InventoryOutboxNotMerchantTooltip"/> <string name="InventoryOutboxNotMerchant"> - [[MARKETPLACE_URL] Торговый центр Second Life] предлагает на продажу более миллиона виртуальных продуктов, и вÑе они Ñозданы жителÑми Second Life. Ð’Ñ‹ тоже можете продавать Ñозданные вами вещи, а также некоторые из вещей, купленных вами. Ðто ÑовÑем неÑложно. ÐаÑтройка выполнÑетÑÑ Ð±ÐµÑплатно. [[LEARN_MORE_URL] Узнайте подробноÑти] или [[CREATE_STORE_URL] Ñоздайте магазин] в торговом центре, чтобы начать торговлю. + ЕÑли вы хотите Ñтать торговцем, [[MARKETPLACE_CREATE_STORE_URL] Ñоздайте магазин]. </string> <string name="InventoryOutboxNoItemsTitle"> - Ðовый ÑпоÑоб отправки вещей в торговый центр - </string> - <string name="InventoryOutboxNoItemsTooltip"> - Перетащите вещи Ñюда, чтобы подготовить их Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð°Ð¶Ð¸ в торговом центре + Ваша папка «ИÑходÑщие» пуÑта. </string> + <string name="InventoryOutboxNoItemsTooltip"/> <string name="InventoryOutboxNoItems"> - ПеретаÑкивайте в Ñту облаÑÑ‚ÑŒ вещи и папки, которые хотите продать. При перетаÑкивании ÑоздаетÑÑ ÐºÐ¾Ð¿Ð¸Ñ Ð²ÐµÑ‰Ð¸ (за иÑключением вещей, недоÑтупных Ð´Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ), поÑтому инвентарь не изменÑетÑÑ. Когда вÑе готово Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ вещей в торговый центр, нажмите кнопку «Передать». Вещи, перемещенные в инвентарь магазина, иÑчезают из Ñтой папки. + Перетащите папки в Ñту облаÑÑ‚ÑŒ и щелкните «Отправить в торговый центр», чтобы выÑтавить их на продажу в [[MARKETPLACE_DASHBOARD_URL] Торговом центре]. </string> <string name="Marketplace Error None"> Ошибок нет @@ -3901,6 +3918,9 @@ support@secondlife.com. <string name="Saved_message"> (Сохранено [LONG_TIMESTAMP]) </string> + <string name="IM_unblock_only_groups_friends"> + Ð”Ð»Ñ Ð¿Ñ€Ð¾Ñмотра Ñтого ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñнимите флажок «Только Ð´Ñ€ÑƒÐ·ÑŒÑ Ð¸ группы могут звонить мне и отправлÑÑ‚ÑŒ IM» в окне «ÐаÑтройки/ПриватноÑть». + </string> <string name="answered_call"> Ðа ваш звонок ответили </string> @@ -4098,7 +4118,7 @@ support@secondlife.com. </string> <string name="uploading_abuse_report"> ЗагружаетÑÑ... - + Жалоба </string> <string name="New Shape"> @@ -4365,7 +4385,8 @@ support@secondlife.com. <string name="words_separator" value=","/> <string name="server_is_down"> ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° наши уÑилиÑ, что-то неожиданно пошло не так. - ОзнакомьтеÑÑŒ Ñ Ð¾Ð¿Ð¸Ñанием извеÑтных проблем в работе Ñтой Ñлужбы на Ñайте status.secondlifegrid.net. + + ОзнакомьтеÑÑŒ Ñ Ð¾Ð¿Ð¸Ñанием извеÑтных проблем в работе Ñтой Ñлужбы на Ñайте status.secondlifegrid.net. ЕÑли проблемы продолжаютÑÑ, то проверьте подключение к Ñети и наÑтройки брандмауÑра. </string> <string name="dateTimeWeekdaysNames"> @@ -4844,6 +4865,9 @@ support@secondlife.com. <string name="Command_Move_Label"> Ходьба / бег / полет </string> + <string name="Command_Outbox_Label"> + Торговые иÑходÑщие + </string> <string name="Command_People_Label"> Люди </string> @@ -4916,6 +4940,9 @@ support@secondlife.com. <string name="Command_Move_Tooltip"> Перемещение аватара </string> + <string name="Command_Outbox_Tooltip"> + ПеренеÑти предметы в торговый центр Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð°Ð¶Ð¸ + </string> <string name="Command_People_Tooltip"> ДрузьÑ, группы и люди поблизоÑти </string> diff --git a/indra/newview/skins/default/xui/tr/floater_about_land.xml b/indra/newview/skins/default/xui/tr/floater_about_land.xml index dde658d64d..a478d347a8 100644 --- a/indra/newview/skins/default/xui/tr/floater_about_land.xml +++ b/indra/newview/skins/default/xui/tr/floater_about_land.xml @@ -306,9 +306,6 @@ Sadece büyük parseller aramada görünür. <panel.string name="push_restrict_region_text"> Ä°tme Yok (Bölge Geçersiz Kılma) </panel.string> - <panel.string name="see_avs_text"> - DiÄŸer parsellerdeki avatarlar bu - </panel.string> <text name="allow_label"> Sakinlere ÅŸunun için izin ver: </text> @@ -371,7 +368,7 @@ Sadece büyük parseller aramada görünür. </text> <texture_picker name="snapshot_ctrl" tool_tip="Bir resim seçmek için tıklayın"/> <text name="allow_label5"> - bu parseldeki avatarları görebilir ve onlarla sohbet edebilir + BaÅŸka parsellerdeki avatarlar bu parseldeki avatarları görebilir ve onlarla sohbet edebilir </text> <check_box label="Avatarları Gör" name="SeeAvatarsCheck" tool_tip="DiÄŸer parsellerdeki avatarların bu parseldeki avatarları görmesine ve onlarla sohbet etmesine, sizin de onları görüp, onlarla sohbet etmenize imkan tanır."/> <text name="landing_point"> @@ -446,20 +443,15 @@ Sadece büyük parseller aramada görünür. <panel.string name="access_estate_defined"> (Gayrimenkul tarafından tanımlanır) </panel.string> - <panel.string name="allow_public_access"> - Kamusal EriÅŸime Ä°zin Ver ([MATURITY]) (Not: Ä°ÅŸaret kaldırılırsa yasaklama çizgileri oluÅŸur) - </panel.string> <panel.string name="estate_override"> Bu seçeneklerden biri veya daha fazlası gayrimenkul düzeyinde ayarlanır </panel.string> - <text name="Limit access to this parcel to:"> - Bu Parsele EriÅŸim - </text> + <check_box label="Kamusal EriÅŸime Ä°zin Ver (Bunun iÅŸaretinin kaldırılması yasaklama çizgileri oluÅŸturacaktır)" name="public_access"/> <text name="Only Allow"> - EriÅŸimi ÅŸununla doÄŸrulanan Sakinlerle Sınırla: + Sadece ÅŸu Sakinlere eriÅŸim izni verin: </text> - <check_box label="Dosyadaki ödeme bilgileri [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Tanınmayan Sakinleri Yasakla."/> - <check_box label="YaÅŸ doÄŸrulama [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Yaşını doÄŸrulamayan Sakinleri yasakla Daha fazla bilgi için [SUPPORT_SITE] adresini ziyaret edin."/> + <check_box label="Ödeme bilgileri kayıtlı [ESTATE_PAYMENT_LIMIT]" name="limit_payment" tool_tip="Sakinlerin bu parsele eriÅŸebilmesi için ödeme bilgilerinin kayıtlı olması gerekir. Daha fazla bilgi için [SUPPORT_SITE] adresini ziyaret edin."/> + <check_box label="YaÅŸ doÄŸrulaması yapılmış [ESTATE_AGE_LIMIT]" name="limit_age_verified" tool_tip="Sakinlerin bu parsele eriÅŸebilmesi için yaÅŸ doÄŸrulamalarının yapılmış olması gerekir. Daha fazla bilgi için [SUPPORT_SITE] adresini ziyaret edin."/> <check_box label="Grup EriÅŸimine Ä°zin Ver: [GROUP]" name="GroupCheck" tool_tip="Genel sekmesinde grup ayarla."/> <check_box label="GeçiÅŸ haklr. ÅŸuna sat:" name="PassCheck" tool_tip="Bu parsele geçici eriÅŸim verir"/> <combo_box name="pass_combo"> diff --git a/indra/newview/skins/default/xui/tr/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/tr/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..a63e1e107e --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_animation_anim_preview.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Anim Preview" title="ANIMATION.ANIM"> + <text name="name_label"> + Ad: + </text> + <text name="description_label"> + Açıklama: + </text> + <button label="Karşıya Yükle (L$[AMOUNT])" name="ok_btn"/> + <button label="Ä°ptal" label_selected="Ä°ptal" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_animation_bvh_preview.xml b/indra/newview/skins/default/xui/tr/floater_animation_bvh_preview.xml new file mode 100644 index 0000000000..f8800c674d --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_animation_bvh_preview.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Animation Preview"> + <floater.string name="failed_to_initialize"> + Hareket baÅŸlatılamadı + </floater.string> + <floater.string name="anim_too_long"> + Animasyon dosyası [LENGTH] saniye uzunluÄŸunda. + +Maksimum animasyon uzunluÄŸu [LENGTH] saniye. + </floater.string> + <floater.string name="failed_file_read"> + Animasyon dosyası okunamadı. + +[STATUS] + </floater.string> + <floater.string name="E_ST_OK"> + Tamam + </floater.string> + <floater.string name="E_ST_EOF"> + Dosyanın zamanından önce sonu. + </floater.string> + <floater.string name="E_ST_NO_CONSTRAINT"> + Kısıtlama tanımı okunamadı. + </floater.string> + <floater.string name="E_ST_NO_FILE"> + BVH dosyası açılamadı. + </floater.string> + <floater.string name="E_ST_NO_HIER"> + Geçersiz HÄ°YERARŞİ üst bilgisi. + </floater.string> + <floater.string name="E_ST_NO_JOINT"> + KÖK veya EKLEM bulunamadı. + </floater.string> + <floater.string name="E_ST_NO_NAME"> + EKLEM adı alınamadı. + </floater.string> + <floater.string name="E_ST_NO_OFFSET"> + OFSET bulunamadı. + </floater.string> + <floater.string name="E_ST_NO_CHANNELS"> + KANALLAR bulunamadı. + </floater.string> + <floater.string name="E_ST_NO_ROTATION"> + Döndürme sırası alınamadı. + </floater.string> + <floater.string name="E_ST_NO_AXIS"> + Döndürme ekseni alınamadı. + </floater.string> + <floater.string name="E_ST_NO_MOTION"> + HAREKET bulunamadı. + </floater.string> + <floater.string name="E_ST_NO_FRAMES"> + kARE SAYISI alınamadı. + </floater.string> + <floater.string name="E_ST_NO_FRAME_TIME"> + Kare zamanı alınamadı. + </floater.string> + <floater.string name="E_ST_NO_POS"> + Konum deÄŸerleri alınamadı. + </floater.string> + <floater.string name="E_ST_NO_ROT"> + Döndürme deÄŸerleri alınamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_FILE"> + Çeviri dosyası açılamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_HEADER"> + Çeviri üst bilgisi okunamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_NAME"> + Çeviri adları okunamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_IGNORE"> + Çeviri yoksay deÄŸeri okunamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_RELATIVE"> + Çeviri nisbi deÄŸeri okunamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_OUTNAME"> + Çeviri çıkış adı deÄŸeri okunamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_MATRIX"> + Çeviri matrisi okunamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGECHILD"> + BirleÅŸtirme alt birim adı alınamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_MERGEPARENT"> + BirleÅŸtirme üst birim adı alınamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_PRIORITY"> + Öncelik deÄŸerleri alınamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_LOOP"> + Döngü (tekrar) deÄŸerleri alınamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEIN"> + Easln (YavaÅŸ BaÅŸlangıç) deÄŸerleri alınamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_EASEOUT"> + EaseOut (YavaÅŸ BitiÅŸ) deÄŸerleri alınamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_HAND"> + El ÅŸekillendirme deÄŸeri alınamadı. + </floater.string> + <floater.string name="E_ST_NO_XLT_EMOTE"> + Duygu ifadesi adı okunamadı. + </floater.string> + <floater.string name="E_ST_BAD_ROOT"> + Yanlış kök eklem adı, "kalça" kullanın + </floater.string> + <text name="name_label"> + Ad: + </text> + <text name="description_label"> + Açıklama: + </text> + <spinner label="Öncelik" name="priority" tool_tip="Bu animasyonun diÄŸer animasyonları geçersiz kılabileceÄŸi kontrolleri"/> + <check_box label="Döngü" name="loop_check" tool_tip="Bu animasyonun döngülenmesini (tekrarlanmasını) saÄŸlar"/> + <spinner label="İç (%)" name="loop_in_point" tool_tip="Döngünün döndüğü animasyon noktasını belirler"/> + <spinner label="Dış (%)" name="loop_out_point" tool_tip="Animasyonda döngünün bittiÄŸi noktayı belirler"/> + <text name="hand_label"> + El DuruÅŸu + </text> + <combo_box name="hand_pose_combo" tool_tip="Ellerin animasyon sırasında neler yaptığını kontrol eder"> + <combo_box.item label="Yayılım" name="Spread"/> + <combo_box.item label="Rahat" name="Relaxed"/> + <combo_box.item label="Her Ä°kisi de Ä°ÅŸaret Ediyor" name="PointBoth"/> + <combo_box.item label="Yumruk" name="Fist"/> + <combo_box.item label="Sol Rahat" name="RelaxedLeft"/> + <combo_box.item label="Sol Ä°ÅŸaret Ediyor" name="PointLeft"/> + <combo_box.item label="Sol Yumruk" name="FistLeft"/> + <combo_box.item label="SaÄŸ Rahat" name="RelaxedRight"/> + <combo_box.item label="SaÄŸ Ä°ÅŸaret Ediyor" name="PointRight"/> + <combo_box.item label="SaÄŸ Yumruk" name="FistRight"/> + <combo_box.item label="Sağı Selamlıyor" name="SaluteRight"/> + <combo_box.item label="Yazı Yazıyor" name="Typing"/> + <combo_box.item label="SaÄŸ Barış" name="PeaceRight"/> + </combo_box> + <text name="emote_label"> + Ä°fade + </text> + <combo_box name="emote_combo" tool_tip="Yüzün animasyon sırasındaki ifadesini kontrol eder"> + <item label="(Hiçbiri)" name="[None]" value=""/> + <item label="Aaaaah" name="Aaaaah" value="Aaaaah"/> + <item label="KorkmuÅŸ" name="Afraid" value="KorkmuÅŸ"/> + <item label="Kızgın" name="Angry" value="Kızgın"/> + <item label="Yaygın GülümseyiÅŸ" name="BigSmile" value="Yaygın GülümseyiÅŸ"/> + <item label="Canı Sıkılmış" name="Bored" value="Canı Sıkılmış"/> + <item label="AÄŸlama" name="Cry" value="AÄŸlama"/> + <item label="Dudak Bükme" name="Disdain" value="Dudak Bükme"/> + <item label="Utanmış" name="Embarrassed" value="Utanmış"/> + <item label="KaÅŸ Çatma" name="Frown" value="KaÅŸ Çatma"/> + <item label="Öpücük" name="Kiss" value="Öpücük"/> + <item label="Gülme" name="Laugh" value="Gülme"/> + <item label="Kahkaha" name="Plllppt" value="Kahkaha"/> + <item label="TiksinmiÅŸ" name="Repulsed" value="TiksinmiÅŸ"/> + <item label="Ãœzgün" name="Sad" value="Ãœzgün"/> + <item label="Omuz Silkme" name="Shrug" value="Omuz Silkme"/> + <item label="Gülümseme" name="Smile" value="Gülümseme"/> + <item label="Sürpriz" name="Surprise" value="Sürpriz"/> + <item label="Göz Kırpma" name="Wink" value="Göz Kırpma"/> + <item label="EndiÅŸelenme" name="Worry" value="EndiÅŸelenme"/> + </combo_box> + <text name="preview_label"> + Åžu sırada önizle + </text> + <combo_box name="preview_base_anim" tool_tip="Animasyon davranışınızı avatarınız genel hareketleri yaparken test etmek için bunu kullanın."> + <item label="Ayakta Duruyor" name="Standing" value="Ayakta Duruyor"/> + <item label="Yürüyor" name="Walking" value="Yürüyor"/> + <item label="Oturuyor" name="Sitting" value="Oturuyor"/> + <item label="Uçuyor" name="Flying" value="Uçuyor"/> + </combo_box> + <spinner label="YavaÅŸ BaÅŸlangıç (saniye)" name="ease_in_time" tool_tip="Animasyonun kaynaÅŸtığı süre (saniye olarak)"/> + <spinner label="YavaÅŸ BitiÅŸ (saniye)" name="ease_out_time" tool_tip="Animasyonun ayrıştığı süre (saniye olarak)"/> + <button name="play_btn" tool_tip="Animasyonunu oynat"/> + <button name="pause_btn" tool_tip="Animasyonunu duraklat"/> + <button name="stop_btn" tool_tip="Animasyo oynatmayı durdur"/> + <text name="bad_animation_text"> + Animasyon dosyası okunamadı. + +Poser 4'ten aktarılan BHV dosyalarını tavsiye ederiz. + </text> + <button label="Karşıya Yükle (L$[AMOUNT])" name="ok_btn"/> + <button label="Ä°ptal" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml index dee17b7bc4..988c845982 100644 --- a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml @@ -2,6 +2,6 @@ <floater name="chat_bar" title="YAKINDAKÄ° SOHBET"> <panel name="bottom_panel"> <line_editor label="Sohbet etmek için buraya tıklayın." name="chat_box" tool_tip="Söylemek için Enter, bağırmak için Ctrl+Enter yapın"/> - <button name="show_nearby_chat" tool_tip="yakın sohbet günlüğünü gösterir/gizler"/> + <button name="show_nearby_chat" tool_tip="Yakın sohbet günlüğünü gösterir/gizler"/> </panel> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/tr/floater_merchant_outbox.xml new file mode 100644 index 0000000000..325d1d9ed9 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_merchant_outbox.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_merchant_outbox" title="SATICI GÄ°DEN KUTUSU"> + <string name="OutboxFolderCount1"> + 1 klasör + </string> + <string name="OutboxFolderCountN"> + [NUM] klasör + </string> + <string name="OutboxImporting"> + Klasörler gönderiliyor... + </string> + <string name="OutboxInitializing"> + BaÅŸlatılıyor... + </string> + <panel label=""> + <panel> + <panel name="outbox_inventory_placeholder_panel"> + <text name="outbox_inventory_placeholder_title"> + Yükleniyor... + </text> + </panel> + </panel> + <panel> + <button label="Pazaryerine Gönder" name="outbox_import_btn" tool_tip="Pazaryeri Vitrinime Gönder"/> + </panel> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_model_wizard.xml b/indra/newview/skins/default/xui/tr/floater_model_wizard.xml deleted file mode 100644 index b3c72ba2da..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="header_panel"> - <text name="header_text"> - Model dosyasını seçin - </text> - </panel> - <panel name="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="header_panel"> - <text name="header_text"> - Modeli optimize et - </text> - </panel> - <text name="description"> - Modeli performans için optimize ettik. Ä°stiyorsanız daha da ayarlayabilirsiniz. - </text> - <panel name="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="header_panel"> - <text name="header_text"> - Fizik ayarlarını yap - </text> - </panel> - <text name="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="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="header_panel"> - <text name="header_text"> - Ä°ncele - </text> - </panel> - <panel name="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="header_panel"> - <text name="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_preview_animation.xml b/indra/newview/skins/default/xui/tr/floater_preview_animation.xml index 1c526c75f9..23b4848333 100644 --- a/indra/newview/skins/default/xui/tr/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/tr/floater_preview_animation.xml @@ -6,6 +6,6 @@ <text name="desc txt"> Açıklama: </text> - <button label="SL Dünyasında Oynat" label_selected="Durdur" name="Anim play btn" tool_tip="Bu animasyonu baÅŸkaları görebilecek ÅŸekilde oynatın"/> - <button label="Yerel Olarak Oynat" label_selected="Durdur" name="Anim audition btn" tool_tip="Bu animasyonu sadece kendinizin görebileceÄŸi ÅŸekilde oynatın"/> + <button label="SL Dünyasında Oynat" label_selected="Durdur" name="Inworld" tool_tip="Bu animasyonu baÅŸkaları görebilecek ÅŸekilde oynatın"/> + <button label="Yerel Olarak Oynat" label_selected="Durdur" name="Locally" tool_tip="Bu animasyonu sadece kendinizin görebileceÄŸi ÅŸekilde oynatın"/> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/tr/floater_test_layout_stacks.xml new file mode 100644 index 0000000000..b479d5f6d6 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_test_layout_stacks.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="LAYOUTSTACK TESTS"/> diff --git a/indra/newview/skins/default/xui/tr/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/tr/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..fcb7d87287 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_test_text_vertical_aligment.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Test Floater" title="TEST PENCERESÄ°"/> diff --git a/indra/newview/skins/default/xui/tr/floater_tools.xml b/indra/newview/skins/default/xui/tr/floater_tools.xml index d4ee9995dd..b0c59ced42 100644 --- a/indra/newview/skins/default/xui/tr/floater_tools.xml +++ b/indra/newview/skins/default/xui/tr/floater_tools.xml @@ -1,5 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="toolbox floater" short_title="Ä°NÅžA ET ARAÇLARI"> + <floater.string name="grid_screen_text"> + Ekran + </floater.string> + <floater.string name="grid_local_text"> + Yerel + </floater.string> + <floater.string name="grid_world_text"> + Dünya + </floater.string> + <floater.string name="grid_reference_text"> + Referans + </floater.string> + <floater.string name="grid_attachment_text"> + Aksesuar + </floater.string> <floater.string name="status_rotate"> Nesneyi döndürmek için renkli bantları sürükleyin </floater.string> @@ -63,7 +78,12 @@ </text> <check_box initial_value="true" label="Dokuları Uzat" name="checkbox stretch textures"/> <check_box initial_value="true" label="Yasla" name="checkbox snap to grid"/> - <button label="Seçenekler..." name="Options..." tool_tip="Ä°lave aÄŸ seçeneklerine bak"/> + <combo_box name="combobox grid mode" tool_tip="Nesneyi konumlandırmak için aÄŸ cetvelini seçin"> + <combo_box.item label="Dünya" name="World"/> + <combo_box.item label="Yerel" name="Local"/> + <combo_box.item label="Referans" name="Reference"/> + </combo_box> + <button label="" name="Options..." tool_tip="Ä°lave aÄŸ seçeneklerine bak"/> <button name="ToolCube" tool_tip="Küp"/> <button name="ToolPrism" tool_tip="Prizma"/> <button name="ToolPyramid" tool_tip="Piramit"/> diff --git a/indra/newview/skins/default/xui/tr/floater_voice_effect.xml b/indra/newview/skins/default/xui/tr/floater_voice_effect.xml index a10da39a69..3534a3fe90 100644 --- a/indra/newview/skins/default/xui/tr/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/tr/floater_voice_effect.xml @@ -42,13 +42,16 @@ <string name="effect_Demon"> Ä°blis </string> + <string name="effect_Female Elf"> + DiÅŸi Cin + </string> <string name="effect_Flirty"> Cilveli </string> <string name="effect_Foxy"> Alımlı </string> - <string name="effect_Halloween_2010_Bonus"> + <string name="effect_Halloween 2010 Bonus"> Halloween_2010_Bonus </string> <string name="effect_Helium"> @@ -57,9 +60,18 @@ <string name="effect_Husky"> Güçlü </string> + <string name="effect_Husky Whisper"> + BoÄŸuk Fısıltı + </string> <string name="effect_Intercom"> Ä°nterkom </string> + <string name="effect_Julia"> + Julia + </string> + <string name="effect_Lo Lilt"> + YavaÅŸ Mırıltı + </string> <string name="effect_Macho"> Maço </string> @@ -69,6 +81,9 @@ <string name="effect_Mini"> Mini </string> + <string name="effect_Model"> + Model + </string> <string name="effect_Nano"> Nano </string> @@ -90,6 +105,9 @@ <string name="effect_Roxanne"> Roxanne </string> + <string name="effect_Rumble"> + Gurultu + </string> <string name="effect_Sabrina"> Sabrina </string> @@ -102,6 +120,9 @@ <string name="effect_Shorty"> Bücür </string> + <string name="effect_Smaller"> + Daha Küçük + </string> <string name="effect_Sneaky"> Sinsi </string> diff --git a/indra/newview/skins/default/xui/tr/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/tr/menu_inspect_object_gear.xml index 02e5415598..d1d3f9ac8d 100644 --- a/indra/newview/skins/default/xui/tr/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/tr/menu_inspect_object_gear.xml @@ -12,6 +12,7 @@ <menu_item_call label="Ekle" name="add"/> <menu_item_call label="Raporla" name="report"/> <menu_item_call label="Engelle" name="block"/> + <menu_item_call label="Engellemeyi Kaldır" name="unblock"/> <menu_item_call label="YakınlaÅŸtır" name="zoom_in"/> <menu_item_call label="Kaldır" name="remove"/> <menu_item_call label="Ek Bilgi" name="more_info"/> diff --git a/indra/newview/skins/default/xui/tr/menu_inventory.xml b/indra/newview/skins/default/xui/tr/menu_inventory.xml index f14066fd7b..170cdebd24 100644 --- a/indra/newview/skins/default/xui/tr/menu_inventory.xml +++ b/indra/newview/skins/default/xui/tr/menu_inventory.xml @@ -59,6 +59,7 @@ <menu_item_call label="Özellikler" name="Properties"/> <menu_item_call label="Yeniden Adlandır" name="Rename"/> <menu_item_call label="Varlık UUID'sini Kopyala" name="Copy Asset UUID"/> + <menu_item_call label="Kes" name="Cut"/> <menu_item_call label="Kopyala" name="Copy"/> <menu_item_call label="Yapıştır" name="Paste"/> <menu_item_call label="BaÄŸlantı Olarak Yapıştır" name="Paste As Link"/> @@ -84,6 +85,6 @@ <menu_item_call label="Ekle" name="Wearable Add"/> <menu_item_call label="Çıkar" name="Take Off"/> <menu_item_call label="Satıcı Giden Kutusuna Kopyala" name="Merchant Copy"/> - <menu_item_call label="Satıcı Giden Kutusuna Taşı" name="Merchant Move"/> + <menu_item_call label="Pazaryerine Gönder" name="Marketplace Send"/> <menu_item_call label="--seçenek yok--" name="--no options--"/> </menu> diff --git a/indra/newview/skins/default/xui/tr/menu_login.xml b/indra/newview/skins/default/xui/tr/menu_login.xml index 4c3539b38b..f27908bf7a 100644 --- a/indra/newview/skins/default/xui/tr/menu_login.xml +++ b/indra/newview/skins/default/xui/tr/menu_login.xml @@ -17,8 +17,8 @@ <menu_item_call label="Pencere Büyüklüğünü Ayarla..." name="Set Window Size..."/> <menu_item_call label="Hizmet Åžartlarını Göster" name="TOS"/> <menu_item_call label="Kritik Ä°letiyi Göster" name="Critical"/> - <menu_item_call label="Ortam Tarayıcı Testi" name="Web Browser Test"/> <menu_item_call label="Web İçeriÄŸi Gezdiricisi Hata Ayıklama Testi" name="Web Content Floater Debug Test"/> + <menu label="Günlük Tutma Seviyesini Seç" name="Set Logging Level"/> <menu_item_check label="Izgara Seçiciyi Göster" name="Show Grid Picker"/> <menu_item_call label="Bildirimler Konsolunu Göster" name="Show Notifications Console"/> </menu> diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml index ef10d639d7..d7b20bac4b 100644 --- a/indra/newview/skins/default/xui/tr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml @@ -14,14 +14,14 @@ <menu_item_check label="Uç" name="Fly"/> <menu_item_check label="Daima KoÅŸ" name="Always Run"/> <menu_item_call label="Beni Anime Etmeyi Durdur" name="Stop Animating My Avatar"/> + <menu_item_call label="Yürü / koÅŸ / uç..." name="Walk / run / fly"/> </menu> <menu label="Durum" name="Status"> <menu_item_call label="Uzakta" name="Set Away"/> <menu_item_call label="MeÅŸgul" name="Set Busy"/> </menu> - <menu_item_call label="Yönetici Durumu Talep Et" name="Request Admin Options"/> - <menu_item_call label="Yönetici Durumundan Ayrıl" name="Leave Admin Options"/> - <menu_item_call label="L$ Satın Al" name="Buy and Sell L$"/> + <menu_item_call label="L$ Satın Al..." name="Buy and Sell L$"/> + <menu_item_call label="Satıcı Giden Kutusu..." name="MerchantOutbox"/> <menu_item_call label="Hesap kontrol paneli..." name="Manage My Account"/> <menu_item_call label="Tercihler..." name="Preferences"/> <menu_item_call label="Araç çubuÄŸu düğmeleri..." name="Toolbars"/> @@ -61,12 +61,12 @@ <menu_item_check label="Parsel Özellikleri" name="Parcel Properties"/> <menu_item_check label="GeliÅŸmiÅŸ Menü" name="Show Advanced Menu"/> </menu> - <menu label="GüneÅŸ" name="Environment Settings"> + <menu label="GüneÅŸ" name="Sun"> <menu_item_call label="Gün DoÄŸumu" name="Sunrise"/> <menu_item_call label="Gün Ortası" name="Noon"/> <menu_item_call label="Gün Batımı" name="Sunset"/> <menu_item_call label="Gece Yarısı" name="Midnight"/> - <menu_item_call label="Bölge Ayarlarını Kullanın" name="Use Region Settings"/> + <menu_item_call label="Bölge Ayarlarını Kullan" name="Use Region Settings"/> </menu> <menu label="Ortam Düzenleyici" name="Environment Editor"> <menu_item_call label="Ortam Ayarları..." name="Environment Settings"/> @@ -176,22 +176,22 @@ <menu_item_check label="Fare Ãœzerinden Görünüm Artı Ä°ÅŸaretini Göster" name="ShowCrosshairs"/> </menu> <menu label="Ä°ÅŸleme Türleri" name="Rendering Types"> - <menu_item_check label="Basit" name="Simple"/> - <menu_item_check label="Alfa" name="Alpha"/> - <menu_item_check label="AÄŸaç" name="Tree"/> - <menu_item_check label="Avatarlar" name="Character"/> - <menu_item_check label="Yüzey Yaması" name="Surface Patch"/> - <menu_item_check label="Gökyüzü" name="Sky"/> - <menu_item_check label="Su" name="Water"/> - <menu_item_check label="Toprak" name="Ground"/> - <menu_item_check label="Hacim" name="Volume"/> - <menu_item_check label="Çimen" name="Grass"/> - <menu_item_check label="Bulutlar" name="Clouds"/> - <menu_item_check label="Parçacıklar" name="Particles"/> - <menu_item_check label="Tümsek" name="Bump"/> + <menu_item_check label="Basit" name="Rendering Type Simple"/> + <menu_item_check label="Alfa" name="Rendering Type Alpha"/> + <menu_item_check label="AÄŸaç" name="Rendering Type Tree"/> + <menu_item_check label="Avatarlar" name="Rendering Type Character"/> + <menu_item_check label="Yüzey Yaması" name="Rendering Type Surface Patch"/> + <menu_item_check label="Gökyüzü" name="Rendering Type Sky"/> + <menu_item_check label="Su" name="Rendering Type Water"/> + <menu_item_check label="Toprak" name="Rendering Type Ground"/> + <menu_item_check label="Hacim" name="Rendering Type Volume"/> + <menu_item_check label="Çimen" name="Rendering Type Grass"/> + <menu_item_check label="Bulutlar" name="Rendering Type Clouds"/> + <menu_item_check label="Parçacıklar" name="Rendering Type Particles"/> + <menu_item_check label="Tümsek" name="Rendering Type Bump"/> </menu> <menu label="Ä°ÅŸleme Özellikleri" name="Rendering Features"> - <menu_item_check label="KA" name="UI"/> + <menu_item_check label="KA" name="ToggleUI"/> <menu_item_check label="Seçili" name="Selected"/> <menu_item_check label="Vurgulanmış" name="Highlighted"/> <menu_item_check label="Dinamik Dokular" name="Dynamic Textures"/> @@ -205,8 +205,6 @@ <menu_item_check label="Fare DüzleÅŸtirme" name="Mouse Smoothing"/> <menu_item_call label="Bırakma Anahtarları" name="Release Keys"/> <menu label="Kısa Yollar" name="Shortcuts"> - <menu_item_call label="Görüntü (L$[COST])..." name="Upload Image"/> - <menu_item_check label="Ara" name="Search"/> <menu_item_check label="GeliÅŸmiÅŸ Menüyü Göster - eski kısayol" name="Show Advanced Menu - legacy shortcut"/> <menu_item_call label="Pencereyi Kapat" name="Close Window"/> <menu_item_call label="Tüm Pencereleri Kapat" name="Close All Windows"/> @@ -215,13 +213,6 @@ <menu_item_check label="Oyun ÇubuÄŸu Flycam" name="Joystick Flycam"/> <menu_item_call label="Görünümü Sıfırla" name="Reset View"/> <menu_item_call label="Son Sohbet Edene Bak" name="Look at Last Chatter"/> - <menu label="Ä°nÅŸa Et Aracını Seç" name="Select Tool"> - <menu_item_call label="Odaklanma Aracı" name="Focus"/> - <menu_item_call label="Hareket Ettirme Aracı" name="Move"/> - <menu_item_call label="Düzenleme Aracı" name="Edit"/> - <menu_item_call label="OluÅŸturma Aracı" name="Create"/> - <menu_item_call label="Arazi Aracı" name="Land"/> - </menu> <menu_item_call label="YakınlaÅŸtır" name="Zoom In"/> <menu_item_call label="Varsayılan YakınlaÅŸtırma" name="Zoom Default"/> <menu_item_call label="UzaklaÅŸtırma" name="Zoom Out"/> @@ -294,6 +285,7 @@ <menu_item_check label="Işın Yayını" name="Raycast"/> <menu_item_check label="Rüzgar Vektörleri" name="Wind Vectors"/> <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> <menu label="Ä°ÅŸleme" name="Rendering"> @@ -335,9 +327,8 @@ <menu_item_call label="Kaydı BaÅŸlat" name="Start Record"/> <menu_item_call label="Kaydı Durdur" name="Stop Record"/> </menu> - <menu label="Dünya" name="World"> + <menu label="Dünya" name="DevelopWorld"> <menu_item_check label="Sim GüneÅŸi Geçersiz Kıl" name="Sim Sun Override"/> - <menu_item_check label="Yanıp Sönen Ä°ÅŸaret" name="Cheesy Beacon"/> <menu_item_check label="Sabit Hava Durumu" name="Fixed Weather"/> <menu_item_call label="Bölge Nesne ÖnbelleÄŸinin Dökümünü Al" name="Dump Region Object Cache"/> </menu> @@ -369,11 +360,11 @@ </menu> <menu label="Avatar" name="Character"> <menu label="KaydedilmiÅŸ Dokuyu Al" name="Grab Baked Texture"> - <menu_item_call label="Ä°ris" name="Iris"/> - <menu_item_call label="BaÅŸ" name="Head"/> - <menu_item_call label="Ãœst Gövde" name="Upper Body"/> - <menu_item_call label="Alt Gövde" name="Lower Body"/> - <menu_item_call label="Etek" name="Skirt"/> + <menu_item_call label="Ä°ris" name="Grab Iris"/> + <menu_item_call label="BaÅŸ" name="Grab Head"/> + <menu_item_call label="Ãœst Gövde" name="Grab Upper Body"/> + <menu_item_call label="Alt Gövde" name="Grab Lower Body"/> + <menu_item_call label="Etek" name="Grab Skirt"/> </menu> <menu label="Karakter Testleri" name="Character Tests"> <menu_item_call label="XML'de Görünüm" name="Appearance To XML"/> @@ -401,17 +392,25 @@ <menu_item_check label="HTTP Dokuları" name="HTTP Textures"/> <menu_item_check label="HTTP Envanteri" name="HTTP Inventory"/> <menu_item_call label="Görüntüleri Sıkıştır" name="Compress Images"/> + <menu_item_call label="Visual Leak Detector'ı EtkinleÅŸtir" name="Enable Visual Leak Detector"/> <menu_item_check label="Mini Döküm Dosyası Hata Ayıklama Çıktısı" name="Output Debug Minidump"/> <menu_item_check label="Sonraki Çalışmada Konsol Penceresi" name="Console Window"/> + <menu label="Günlük Tutma Seviyesini Seç" name="Set Logging Level"> + <menu_item_check label="Hata ayıkla" name="Debug"/> + <menu_item_check label="Bilgi" name="Info"/> + <menu_item_check label="Uyarı" name="Warning"/> + <menu_item_check label="Hata" name="Error"/> + <menu_item_check label="Hiçbiri" name="None"/> + </menu> <menu_item_call label="Yönetici Durumu Talep Et" name="Request Admin Options"/> <menu_item_call label="Yönetici Durumundan Ayrıl" name="Leave Admin Options"/> <menu_item_check label="Yönetici Menüsünü Göster" name="View Admin Options"/> </menu> <menu label="Yönetici" name="Admin"> - <menu label="Object"> - <menu_item_call label="Kopya Al" name="Take Copy"/> - <menu_item_call label="Mülkiyetime Geçir" name="Force Owner To Me"/> - <menu_item_call label="Ä°zinlerle Birlikte Mülkiyetime Geçir" name="Force Owner Permissive"/> + <menu label="Nesne" name="AdminObject"> + <menu_item_call label="Kopya Al" name="Admin Take Copy"/> + <menu_item_call label="Zorunlu Olarak Mülkiyetime Geçir" name="Force Owner To Me"/> + <menu_item_call label="Sahibin Ä°zinlerini Zorunlu Kıl" name="Force Owner Permissive"/> <menu_item_call label="Sil" name="Delete"/> <menu_item_call label="Kilitle" name="Lock"/> <menu_item_call label="Varlık Kimliklerini Al" name="Get Assets IDs"/> @@ -445,7 +444,7 @@ <menu_item_call label="Fizik" name="Physics"/> <menu_item_call label="Tüm Giysiler" name="All Clothes"/> </menu> - <menu label="Yardım" name="Help"> + <menu label="Yardım" name="DeprecatedHelp"> <menu_item_call label="Resmi Linden Blog'u" name="Official Linden Blog"/> <menu_item_call label="Komut Dosyası Portalı" name="Scripting Portal"/> <menu label="Hata Raporlama" name="Bug Reporting"> diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml index 631634aa7d..6681cdac7a 100644 --- a/indra/newview/skins/default/xui/tr/notifications.xml +++ b/indra/newview/skins/default/xui/tr/notifications.xml @@ -86,17 +86,38 @@ Hata ayrıntıları: '[_NAME]' adlı bildirim notifications.xml içind <usetemplate canceltext="Ä°ptal" name="yesnocancelbuttons" notext="Kaydetme" yestext="Kaydet"/> </notification> <notification name="ConfirmNoCopyToOutbox"> - Bu öğeyi Pazaryeri Giden Kutunuza kopyalama izniniz yok. AÅŸağıdaki öğeyi taşımak istediÄŸinize emin misiniz? - [ITEM_NAME] - <usetemplate name="okcancelbuttons" notext="Hayır" yestext="Evet"/> + Bu öğelerden bir veya daha fazlasını Satıcı Giden Kutusuna kopyalama izniniz yok. Bunları taşıyabilir veya bırakabilirsiniz. + <usetemplate name="okcancelbuttons" notext="Öğeleri taşıma" yestext="Öğeleri taşı"/> + </notification> + <notification name="OutboxFolderCreated"> + Satıcı Giden Kutunuzun üst seviyesine aktardığınız her bir öğe için yeni bir klasör oluÅŸturuldu. + <usetemplate ignoretext="Satıcı Giden Kutusunda yeni bir klasör oluÅŸturuldu" name="okignore" yestext="Tamam"/> </notification> - <notification name="OutboxUploadComplete"> - Pazaryerinin karşıya yüklenmesi tamamlandı. - <usetemplate name="okbutton" yestext="YaÅŸasın!"/> + <notification name="OutboxImportComplete"> + BaÅŸarılı oldu + +Tüm klasörler baÅŸarıyla Pazaryerine gönderildi. + <usetemplate ignoretext="Tüm klasörler Pazaryerine gönderildi" name="okignore" yestext="Tamam"/> </notification> - <notification name="OutboxUploadHadErrors"> - Pazaryerinin karşıya yüklenmesi hatalarla tamamlandı! Lütfen giden kutunuzdaki sorunları düzeltin ve tekrar deneyin. TeÅŸekkürler. - <usetemplate name="okbutton" yestext="Yuh!"/> + <notification name="OutboxImportHadErrors"> + Bazı klasörler aktarılmadı + +Bazı klasörler Pazaryerine gönderildiÄŸinde hatalar meydana geldi. Bu klasörler hala Satıcı Giden Kutunuzda. + +Daha fazla bilgi için bkz. [[MARKETPLACE_IMPORTS_URL] hata günlüğü]. + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="OutboxImportFailed"> + Aktarım baÅŸarılamadı + +Bir sistem veya aÄŸ hatası nedeniyle Pazaryerine hiçbir klasör gönderilemedi. Daha sonra tekrar deneyin. + <usetemplate name="okbutton" yestext="Tamam"/> + </notification> + <notification name="OutboxInitFailed"> + Pazaryeri baÅŸlatılamadı. + +Bir sistem veya aÄŸ hatası nedeniyle Pazaryeri baÅŸlatılamadı. Daha sonra tekrar deneyin. + <usetemplate name="okbutton" yestext="Tamam"/> </notification> <notification name="CompileQueueSaveText"> AÅŸağıdaki nedenden dolayı, bir komut dosyası için metin karşıya yüklenirken bir sorun oluÅŸtu: [REASON]. Lütfen daha sonra tekrar deneyin. @@ -649,7 +670,7 @@ Beklenen [VALIDS] Çıkış dosyası oluÅŸturulamıyor: [FILE] </notification> <notification name="DoNotSupportBulkAnimationUpload"> - [APP_NAME] ÅŸu an için animasyon dosyalarının toplu olarak karşıya yüklenmesini desteklemiyor. + [APP_NAME] ÅŸu an için BVH formatında animasyon dosyalarının toplu olarak yüklenmesini desteklemiyor. </notification> <notification name="CannotUploadReason"> AÅŸağıdaki nedenden dolayı [FILE] dosyası karşıya yüklenemedi: [REASON] @@ -2609,16 +2630,16 @@ Talep kabul edilsin mi? [NAME] adlı kiÅŸiye ait '<nolink>[TITLE]</nolink>' [MESSAGE] <form name="form"> - <button name="Mute" text="Engelle"/> - <button name="Ignore" text="Yok say"/> + <button name="Client_Side_Mute" text="Engelle"/> + <button name="Client_Side_Ignore" text="Yok say"/> </form> </notification> <notification name="ScriptDialogGroup"> [GROUPNAME] grubuna ait '<nolink>[TITLE]</nolink>' [MESSAGE] <form name="form"> - <button name="Mute" text="Engelle"/> - <button name="Ignore" text="Yok say"/> + <button name="Client_Side_Mute" text="Engelle"/> + <button name="Client_Side_Ignore" text="Yok say"/> </form> </notification> <notification name="BuyLindenDollarSuccess"> @@ -2816,6 +2837,18 @@ PaylaÅŸmanın yapılacağı Sakinler: [RESIDENTS] <usetemplate name="okcancelbuttons" notext="Ä°ptal" yestext="Tamam"/> </notification> + <notification name="ShareFolderConfirmation"> + Bir defada sadece bir klasör paylaşılabilir. + +AÅŸağıdaki öğeleri paylaÅŸmak istediÄŸinize emin misiniz? + +<nolink>[ITEMS]</nolink> + +PaylaÅŸmanın yapılacağı Second Life Sakinleri: + +[RESIDENTS] + <usetemplate name="okcancelbuttons" notext="Ä°ptal" yestext="Tamam"/> + </notification> <notification name="ItemsShared"> Öğeler baÅŸarılı bir ÅŸekilde paylaşıldı. </notification> diff --git a/indra/newview/skins/default/xui/tr/panel_nearby_chat.xml b/indra/newview/skins/default/xui/tr/panel_nearby_chat.xml index c405105e00..d238388b0e 100644 --- a/indra/newview/skins/default/xui/tr/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/tr/panel_nearby_chat.xml @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="nearby_chat"> - <check_box label="Sohbeti çevir" name="translate_chat_checkbox"/> + <layout_stack name="stack"> + <layout_panel name="translate_chat_checkbox_lp"> + <check_box label="Sohbeti çevir" name="translate_chat_checkbox"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_region_estate.xml b/indra/newview/skins/default/xui/tr/panel_region_estate.xml index 4ba55cafb6..f1df13df61 100644 --- a/indra/newview/skins/default/xui/tr/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/tr/panel_region_estate.xml @@ -20,10 +20,10 @@ <slider label="Faz" name="sun_hour_slider"/> <check_box label="Kamusal EriÅŸime Ä°zin Ver" name="externally_visible_check"/> <text name="Only Allow"> - EriÅŸimi ÅŸununla doÄŸrulanan hesaplarla sınırla: + Sadece ÅŸu Sakinlere eriÅŸim izni verin: </text> - <check_box label="Dosyadaki Ödeme Bilgileri" name="limit_payment" tool_tip="Tanınmayan Sakinleri Yasakla"/> - <check_box label="YaÅŸ DoÄŸrulama" name="limit_age_verified" tool_tip="Yaşını doÄŸrulamayan Sakinleri yasakla Daha fazla bilgi için [SUPPORT_SITE] adresini ziyaret edin."/> + <check_box label="Ödeme bilgileri kayıtlı" name="limit_payment" tool_tip="Sakinlerin bu gayrimenkule eriÅŸebilmesi için ödeme bilgilerinin kayıtlı olması gerekir. Daha fazla bilgi için [SUPPORT_SITE] adresini ziyaret edin."/> + <check_box label="YaÅŸ doÄŸrulaması yapılmış" name="limit_age_verified" tool_tip="Sakinlerin bu gayrimenkule eriÅŸebilmesi için yaÅŸ doÄŸrulamalarının yapılmış olması gerekir. Daha fazla bilgi için [SUPPORT_SITE] adresini ziyaret edin."/> <check_box label="Sesli Sohbete Ä°zin Ver" name="voice_chat_check"/> <check_box label="DoÄŸrudan Işınlamaya Ä°zin Ver" name="allow_direct_teleport"/> <button label="Uygula" name="apply_btn"/> diff --git a/indra/newview/skins/default/xui/tr/panel_script_ed.xml b/indra/newview/skins/default/xui/tr/panel_script_ed.xml index bc30320fa5..7aa1da6fb2 100644 --- a/indra/newview/skins/default/xui/tr/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/tr/panel_script_ed.xml @@ -22,6 +22,8 @@ <menu label="Dosya" name="File"> <menu_item_call label="Kaydet" name="Save"/> <menu_item_call label="Tüm DeÄŸiÅŸiklikleri Geri Çevir" name="Revert All Changes"/> + <menu_item_call label="Dosyadan yükle..." name="LoadFromFile"/> + <menu_item_call label="Dosyaya kaydet..." name="SaveToFile"/> </menu> <menu label="Düzenle" name="Edit"> <menu_item_call label="Geri Al" name="Undo"/> diff --git a/indra/newview/skins/default/xui/tr/panel_status_bar.xml b/indra/newview/skins/default/xui/tr/panel_status_bar.xml index 81c304a5d8..178cbda4a2 100644 --- a/indra/newview/skins/default/xui/tr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/tr/panel_status_bar.xml @@ -15,7 +15,7 @@ <panel.string name="buycurrencylabel"> L$ [AMT] </panel.string> - <panel name="balance_bg"> + <panel left="-425" name="balance_bg" width="215"> <text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$20"/> <button label="L$ Satın Al" name="buyL" tool_tip="Daha fazla L$ satın almak için tıklayın"/> <button label="AlışveriÅŸ yap" name="goShop" tool_tip="Second Life Pazaryeri Aç" width="95"/> diff --git a/indra/newview/skins/default/xui/tr/sidepanel_inventory.xml b/indra/newview/skins/default/xui/tr/sidepanel_inventory.xml index 70c449b402..938b5a76d8 100644 --- a/indra/newview/skins/default/xui/tr/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/tr/sidepanel_inventory.xml @@ -2,47 +2,24 @@ <panel label="EÅŸyalar" name="objects panel"> <panel label="" name="sidepanel__inventory_panel"> <layout_stack name="inventory_layout_stack"> - <layout_panel name="inbox_outbox_layout_panel"> - <layout_stack name="inbox_outbox_layout_stack"> - <layout_panel name="inbox_layout_panel"> - <panel label="" name="marketplace_inbox"> - <string name="InboxLabelWithArg"> - Alınan öğeler ([NUM]) - </string> - <string name="InboxLabelNoArg"> - Alınan öğeler - </string> - <button label="Alınan öğeler" name="inbox_btn"/> - <text name="inbox_fresh_new_count"> - [NUM] yeni - </text> - <panel tool_tip="Drag and drop items to your inventory to manage and use them"> - <text name="inbox_inventory_placeholder"> - Pazaryerinden satın alınan öğeler buraya teslim edilir. - </text> - </panel> - </panel> - </layout_panel> - <layout_panel name="outbox_layout_panel"> - <panel label="" name="marketplace_outbox"> - <string name="OutboxLabelWithArg"> - Satıcı giden kutusu ([NUM]) - </string> - <string name="OutboxLabelNoArg"> - Satıcı giden kutusu - </string> - <button label="Satıcı giden kutusu" name="outbox_btn"/> - <button label="" name="outbox_sync_btn" tool_tip="Pazaryeri Vitrinime Gönder"/> - <panel> - <panel name="outbox_inventory_placeholder_panel"> - <text name="outbox_inventory_placeholder_title"> - Yükleniyor... - </text> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> + <layout_panel name="inbox_layout_panel"> + <panel label="" name="marketplace_inbox"> + <string name="InboxLabelWithArg"> + Alınan öğeler ([NUM]) + </string> + <string name="InboxLabelNoArg"> + Alınan öğeler + </string> + <button label="Alınan öğeler" name="inbox_btn"/> + <text name="inbox_fresh_new_count"> + [NUM] yeni + </text> + <panel name="inbox_inventory_placeholder_panel" tool_tip="Öğeleri kullanmak için bunları sürükleyin ve envanterinize bırakın"> + <text name="inbox_inventory_placeholder"> + Pazaryerinden satın alınan öğeler buraya teslim edilir. + </text> + </panel> + </panel> </layout_panel> </layout_stack> <panel name="button_panel"> diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index 0dbc9b0a0e..2a4e2c20a7 100644 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -181,7 +181,7 @@ GüncelleÅŸtirmeler için www.secondlife.com/status adresini kontrol edin. </string> <string name="LoginFailedPremiumOnly"> Second Life üzerindeki aktif kullanıcıların olası en iyi deneyimi yaÅŸamasını saÄŸlamak için, oturum açılması geçici olarak kısıtlanmıştır. - + Second Life için ödeme yapmış olan kiÅŸilere öncelik tanımak amacıyla, ücretsiz hesaplara sahip kiÅŸiler bu süre içerisinde Second Life'a eriÅŸemeyecekler. </string> <string name="LoginFailedComputerProhibited"> @@ -339,17 +339,35 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. Buraya sadece bir öğe sürüklenebilir. </string> <string name="TooltipPrice" value="L$[AMOUNT]:"/> + <string name="TooltipOutboxDragToWorld"> + Satıcı giden kutunuzda öğeler oluÅŸturamazsınız + </string> <string name="TooltipOutboxNoTransfer"> - Bu nesnelerden bir veya daha fazlası baÅŸka bir kullanıcıya satılamaz veya aktarılamaz. + Bu nesnelerden bir veya daha fazlası satılamaz veya aktarılamaz. + </string> + <string name="TooltipOutboxNotInInventory"> + Satıcı giden kutunuza sadece doÄŸrudan kendi envanterinizden öğeler koyabilirsiniz </string> <string name="TooltipOutboxWorn"> - Bu nesnelerden bir veya daha fazlasını giyiyorsunuz. Bunları avatarınızdan kaldırın ve tekrar taşımayı deneyin. + Giymekte olduÄŸunuz öğeleri Satıcı giden kutunuza koyamazsınız. + </string> + <string name="TooltipOutboxCallingCard"> + Satıcı giden kutunuza arama kartları koyamazsınız </string> <string name="TooltipOutboxFolderLevels"> - Bu klasörde çok fazla alt klasör seviyesi var. Dahili klasörleri tekrar düzenleyerek maksimum 4 seviye derinliÄŸe azaltın (Kök Klasör içinde A içinde B içinde C ÅŸeklinde). + İç içe geçmiÅŸ klasörlerin derinliÄŸi üçü geçiyor + </string> + <string name="TooltipOutboxTooManyFolders"> + Ãœst seviyedeki klasördeki alt klasör sayısı 20'yi geçiyor </string> <string name="TooltipOutboxTooManyObjects"> - Bu klasörde 200'den fazla nesne var. Nesne sayısını azaltmak için öğelerden bazılarını kutuya koyun. + Ãœst seviyedeki klasördeki öğe sayısı 200'ü geçiyor + </string> + <string name="TooltipDragOntoOwnChild"> + Bir klasörü alt klasörüne taşıyamazsınız + </string> + <string name="TooltipDragOntoSelf"> + Bir klasörü kendi içine taşıyamazsınız </string> <string name="TooltipHttpUrl"> Bu web sayfasını görmek için tıklayın @@ -814,6 +832,9 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="anim_yes_head"> Evet </string> + <string name="multiple_textures"> + Birden Çok + </string> <string name="texture_loading"> Yükleniyor... </string> @@ -973,6 +994,9 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="choose_the_directory"> Dizin Seç </string> + <string name="script_files"> + Komut Dosyaları + </string> <string name="AvatarSetNotAway"> Uzakta DeÄŸil </string> @@ -1211,43 +1235,36 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. Envanterinizde bu dokunun kopyası yok </string> <string name="InventoryInboxNoItems"> - Bir öğeyi satın aldığınızda veya baÅŸka bir ÅŸekilde edindiÄŸinizde burada görünür; bunu envanterinizdeki bir klasöre sürükleyebilir veya tutmak istemiyorsanız silebilirsiniz. + Pazaryerinda satın aldıklarınız burada görünecektir. Bunları kullanmak için envanterinize sürükleyebilirsiniz. </string> <string name="MarketplaceURL"> - http://marketplace.[DOMAIN_NAME] + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/ </string> <string name="MarketplaceURL_CreateStore"> - http://marketplace.[DOMAIN_NAME]/create_store - </string> - <string name="MarketplaceURL_LearnMore"> - http://marketplace.[DOMAIN_NAME]/learn_more + http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4 </string> - <string name="InventoryOutboxCreationErrorTitle"> - Satıcı Giden Kutunuz düzgün yapılandırılmamıştır + <string name="MarketplaceURL_Dashboard"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard </string> - <string name="InventoryOutboxCreationErrorTooltip"> - Satıcı Giden Kutusu yapılandırma hatası + <string name="MarketplaceURL_Imports"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports </string> - <string name="InventoryOutboxCreationError"> - Sorunu düzeltmek için lütfen Müşteri Hizmetlerine baÅŸvurun. + <string name="MarketplaceURL_LearnMore"> + https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more </string> <string name="InventoryOutboxNotMerchantTitle"> - Pazaryerinde herkes öğe satabilir - </string> - <string name="InventoryOutboxNotMerchantTooltip"> - Bir satıcı olun! + Pazaryerinde herkes öğe satabilir. </string> + <string name="InventoryOutboxNotMerchantTooltip"/> <string name="InventoryOutboxNotMerchant"> - [[MARKETPLACE_URL] Second Life Pazaryeri] içerisinde bir milyondan fazla sanal ürün satışa sunulmuÅŸtur, bunların tümü Sakinler tarafından oluÅŸturulmuÅŸtur. Siz de oluÅŸturduÄŸunuz öğeleri ve satın aldığınız öğelerin bazılarını satabilirsiniz. Bunu yapmak kolaydır, kurulum da ücretsizdir. [[LEARN_MORE_URL] Daha fazla bilgi edinin] veya baÅŸlamak için Pazaryerinde [[CREATE_STORE_URL] bir maÄŸaza açın]. + EÄŸer bir satıcı olmak istiyorsanız, [Pazaryerinde [MARKETPLACE_CREATE_STORE_URL] bir maÄŸaza açmanız gerekir]. </string> <string name="InventoryOutboxNoItemsTitle"> - Pazaryerine öğe göndermek için yeni bir yol - </string> - <string name="InventoryOutboxNoItemsTooltip"> - Öğeleri Pazaryerinde satışa hazırlamak için sürükleyip buraya bırakın + Giden kutunuz boÅŸ. </string> + <string name="InventoryOutboxNoItemsTooltip"/> <string name="InventoryOutboxNoItems"> - Satmak istediÄŸiniz öğeleri veya klasörleri bu alana sürükleyin. Öğenin bir kopyası burada görünür ve kopyalanamaz bir öğeyi sürüklemediyseniz, envanteriniz aynı kalır. Öğeleri Pazaryerine göndermeye hazır olduÄŸunuzda Karşıya Yükle düğmesine tıklayın. Öğeleriniz Pazaryeri Envanterinize taşındığında bu klasörden kaybolurlar. + Bu alana klasörleri sürükleyin ve bunları [[MARKETPLACE_DASHBOARD_URL] Pazaryerinde] satılık olarak duyurmak için "Pazaryerine Gönder" üzerine tıklayın. </string> <string name="Marketplace Error None"> Hata yok @@ -3904,6 +3921,9 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne baÅŸvurun. <string name="Saved_message"> (Kaydedildi [LONG_TIMESTAMP]) </string> + <string name="IM_unblock_only_groups_friends"> + Bu mesajı görmek için Tercihler/Gizlilik'de 'Sadece arkadaÅŸlar ve gruplar beni arasın veya AÄ° göndersin' seçeneÄŸinin iÅŸaretini kaldırmalısınız. + </string> <string name="answered_call"> Aramanız yanıtlandı </string> @@ -4100,9 +4120,7 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne baÅŸvurun. Çevrimiçi </string> <string name="uploading_abuse_report"> - Karşıya Yükleniyor... - -Kötüye Kullanımı Bildirme + Kötüye Kullanım Bildirimi Karşıya Yükleniyor... </string> <string name="New Shape"> Yeni Åžekil @@ -4369,7 +4387,7 @@ Kötüye Kullanımı Bildirme <string name="server_is_down"> Tüm çabalarımıza raÄŸmen beklenmeyen bir hata meydana geldi. - Hizmetle iliÅŸkili bilinen bir sorun olup olmadığını görmek için lütfen status.secondlifegrid.net adresine bakın. + Hizmetle iliÅŸkili bilinen bir sorun olup olmadığını görmek için lütfen status.secondlifegrid.net adresine bakın. Sorun yaÅŸamaya devam ederseniz lütfen ağınızın ve güvenlik duvarınızın ayarlarına bakın. </string> <string name="dateTimeWeekdaysNames"> @@ -4848,6 +4866,9 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin. <string name="Command_Move_Label"> Yürü / koÅŸ / uç </string> + <string name="Command_Outbox_Label"> + Satıcı giden kutusu + </string> <string name="Command_People_Label"> KiÅŸiler </string> @@ -4920,6 +4941,9 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin. <string name="Command_Move_Tooltip"> Avatarınızı hareket ettirmek </string> + <string name="Command_Outbox_Tooltip"> + Satmak amacıyla Pazaryerinize öğeler taşıyın + </string> <string name="Command_People_Tooltip"> ArkadaÅŸlar, gruplar ve yakındaki kiÅŸiler </string> diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index 3faddc13c1..f8923b9868 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -35,6 +35,31 @@ #include "lluuid.h" #include "llsdutil.h" #include "llregionhandle.h" +#include "../llvoavatar.h" + +void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) +{ + counts.resize(3); + counts[0] = 0; + counts[1] = 0; + counts[2] = 1; +} + +// static +std::string LLVOAvatar::rezStatusToString(S32 rez_status) +{ + if (rez_status==0) return "cloud"; + if (rez_status==1) return "gray"; + if (rez_status==2) return "textured"; + return "unknown"; +} + +// static +LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name) +{ + static LLViewerStats::StatsAccumulator junk; + return junk; +} static const char * all_keys[] = { @@ -104,18 +129,25 @@ is_single_key_map(const LLSD & sd, const std::string & key) { return sd.isMap() && 1 == sd.size() && sd.has(key); } -#endif static bool is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2) { return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2); } +#endif + +static bool +is_triple_key_map(const LLSD & sd, const std::string & key1, const std::string & key2, const std::string& key3) +{ + return sd.isMap() && 3 == sd.size() && sd.has(key1) && sd.has(key2) && sd.has(key3); +} + static bool is_no_stats_map(const LLSD & sd) { - return is_double_key_map(sd, "duration", "regions"); + return is_triple_key_map(sd, "duration", "regions", "avatar"); } static bool @@ -226,7 +258,7 @@ namespace tut // Once the region is set, we will get a response even with no data collection it->setRegion(region1_handle); sd_full = it->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd_full, "duration", "regions", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd_full["regions"], region1_handle)); LLSD sd = sd_full["regions"][0]; @@ -267,7 +299,7 @@ namespace tut it->setRegion(region1_handle); LLSD sd = it->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd[0]; @@ -292,7 +324,7 @@ namespace tut LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); LLSD sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd["regions"][0]; @@ -332,7 +364,7 @@ namespace tut LLSD sd = gViewerAssetStatsThread1->asLLSD(false); ensure("Other collector is empty", is_no_stats_map(sd)); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd["regions"][0]; @@ -382,7 +414,7 @@ namespace tut // std::cout << sd << std::endl; - ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); + ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); LLSD sd1 = get_region(sd, region1_handle); LLSD sd2 = get_region(sd, region2_handle); @@ -405,7 +437,7 @@ namespace tut // Reset leaves current region in place gViewerAssetStatsMain->reset(); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); sd2 = sd["regions"][0]; @@ -454,7 +486,7 @@ namespace tut LLSD sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); + ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); LLSD sd1 = get_region(sd, region1_handle); LLSD sd2 = get_region(sd, region2_handle); @@ -477,7 +509,7 @@ namespace tut // Reset leaves current region in place gViewerAssetStatsMain->reset(); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar")); ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); sd2 = get_region(sd, region2_handle); ensure("Region2 is present in results", sd2.isMap()); @@ -523,7 +555,7 @@ namespace tut LLSD sd = gViewerAssetStatsThread1->asLLSD(false); ensure("Other collector is empty", is_no_stats_map(sd)); sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = get_region(sd, region1_handle); ensure("Region1 is present in results", sd.isMap()); diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp index 4c0959d1a9..e7ef017760 100644 --- a/indra/newview/tests/llworldmipmap_test.cpp +++ b/indra/newview/tests/llworldmipmap_test.cpp @@ -100,9 +100,9 @@ namespace tut { S32 level = mMap->scaleToLevel(0.0); ensure("scaleToLevel() test 1 failed", level == LLWorldMipmap::MAP_LEVELS); - level = mMap->scaleToLevel(LLWorldMipmap::MAP_TILE_SIZE); + level = mMap->scaleToLevel((F32)LLWorldMipmap::MAP_TILE_SIZE); ensure("scaleToLevel() test 2 failed", level == 1); - level = mMap->scaleToLevel(10 * LLWorldMipmap::MAP_TILE_SIZE); + level = mMap->scaleToLevel(10.f * LLWorldMipmap::MAP_TILE_SIZE); ensure("scaleToLevel() test 3 failed", level == 1); } // Test 2 : globalToMipmap() diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 0931c4ec9b..36267803e3 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1025,41 +1025,47 @@ class Linux_i686Manifest(LinuxManifest): super(Linux_i686Manifest, self).construct() if self.prefix("../packages/lib/release", dst="lib"): - self.path("libapr-1.so") - self.path("libapr-1.so.0") - self.path("libapr-1.so.0.4.2") - self.path("libaprutil-1.so") - self.path("libaprutil-1.so.0") - self.path("libaprutil-1.so.0.3.10") - self.path("libbreakpad_client.so.0.0.0") - self.path("libbreakpad_client.so.0") - self.path("libbreakpad_client.so") + self.path("libapr-1.so*") + self.path("libaprutil-1.so*") + self.path("libbreakpad_client.so*") self.path("libcollada14dom.so") - self.path("libdb-5.1.so") - self.path("libdb-5.so") - self.path("libdb.so") - self.path("libcrypto.so.1.0.0") - self.path("libexpat.so.1.5.2") + self.path("libdb*.so") + self.path("libcrypto.so.*") + self.path("libexpat.so.*") self.path("libssl.so.1.0.0") self.path("libglod.so") self.path("libminizip.so") - self.path("libuuid.so") - self.path("libuuid.so.16") - self.path("libuuid.so.16.0.22") - self.path("libSDL-1.2.so.0.11.3") - self.path("libdirectfb-1.4.so.5.0.4") - self.path("libfusion-1.4.so.5.0.4") - self.path("libdirect-1.4.so.5.0.4") - self.path("libopenjpeg.so.1.4.0") - self.path("libopenjpeg.so.1") - self.path("libopenjpeg.so") + self.path("libuuid.so*") + self.path("libSDL-1.2.so.*") + self.path("libdirectfb-1.*.so.*") + self.path("libfusion-1.*.so.*") + self.path("libdirect-1.*.so.*") + self.path("libopenjpeg.so*") + self.path("libdirectfb-1.4.so.5") + self.path("libfusion-1.4.so.5") + self.path("libdirect-1.4.so.5") self.path("libalut.so") self.path("libopenal.so", "libopenal.so.1") self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname - self.path("libfontconfig.so.1.4.4") - self.path("libtcmalloc.so", "libtcmalloc.so") #formerly called google perf tools - self.path("libtcmalloc.so.0", "libtcmalloc.so.0") #formerly called google perf tools - self.path("libtcmalloc.so.0.1.0", "libtcmalloc.so.0.1.0") #formerly called google perf tools + # KLUDGE: As of 2012-04-11, the 'fontconfig' package installs + # libfontconfig.so.1.4.4, along with symlinks libfontconfig.so.1 + # and libfontconfig.so. Before we added support for library-file + # wildcards, though, this self.path() call specifically named + # libfontconfig.so.1.4.4 WITHOUT also copying the symlinks. When I + # (nat) changed the call to self.path("libfontconfig.so.*"), we + # ended up with the libfontconfig.so.1 symlink in the target + # directory as well. But guess what! At least on Ubuntu 10.04, + # certain viewer fonts look terrible with libfontconfig.so.1 + # present in the target directory. Removing that symlink suffices + # to improve them. I suspect that means we actually do better when + # the viewer fails to find our packaged libfontconfig.so*, falling + # back on the system one instead -- but diagnosing and fixing that + # is a bit out of scope for the present project. Meanwhile, this + # particular wildcard specification gets us exactly what the + # previous call did, without having to explicitly state the + # version number. + self.path("libfontconfig.so.*.*") + self.path("libtcmalloc.so*") #formerly called google perf tools try: self.path("libfmod-3.75.so") pass diff --git a/indra/test/catch_and_store_what_in.h b/indra/test/catch_and_store_what_in.h new file mode 100644 index 0000000000..59f8cc0085 --- /dev/null +++ b/indra/test/catch_and_store_what_in.h @@ -0,0 +1,86 @@ +/** + * @file catch_and_store_what_in.h + * @author Nat Goodspeed + * @date 2012-02-15 + * @brief CATCH_AND_STORE_WHAT_IN() macro + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_CATCH_AND_STORE_WHAT_IN_H) +#define LL_CATCH_AND_STORE_WHAT_IN_H + +/** + * Idiom useful for test programs: catch an expected exception, store its + * what() string in a specified std::string variable. From there the caller + * can do things like: + * @code + * ensure("expected exception not thrown", ! string.empty()); + * @endcode + * or + * @code + * ensure_contains("exception doesn't mention blah", string, "blah"); + * @endcode + * etc. + * + * The trouble is that when linking to a dynamic libllcommon.so on Linux, we + * generally fail to catch the specific exception. Oddly, we can catch it as + * std::runtime_error and validate its typeid().name(), so we do -- but that's + * a lot of boilerplate per test. Encapsulate with this macro. Usage: + * + * @code + * std::string threw; + * try + * { + * some_call_that_should_throw_Foo(); + * } + * CATCH_AND_STORE_WHAT_IN(threw, Foo) + * ensure("some_call_that_should_throw_Foo() didn't throw", ! threw.empty()); + * @endcode + */ +#define CATCH_AND_STORE_WHAT_IN(THREW, EXCEPTION) \ +catch (const EXCEPTION& ex) \ +{ \ + (THREW) = ex.what(); \ +} \ +CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION) + +#ifndef LL_LINUX +#define CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION) \ + /* only needed on Linux */ +#else // LL_LINUX + +#define CATCH_MISSED_LINUX_EXCEPTION(THREW, EXCEPTION) \ +catch (const std::runtime_error& ex) \ +{ \ + /* This clause is needed on Linux, on the viewer side, because */ \ + /* the exception isn't caught by catch (const EXCEPTION&). */ \ + /* But if the expected exception was thrown, allow the test to */ \ + /* succeed anyway. Not sure how else to handle this odd case. */ \ + if (std::string(typeid(ex).name()) == typeid(EXCEPTION).name()) \ + { \ + /* std::cerr << "Caught " << typeid(ex).name() */ \ + /* << " with Linux workaround" << std::endl; */ \ + (THREW) = ex.what(); \ + /*std::cout << ex.what() << std::endl;*/ \ + } \ + else \ + { \ + /* We don't even recognize this exception. Let it propagate */ \ + /* out to TUT to fail the test. */ \ + throw; \ + } \ +} \ +catch (...) \ +{ \ + std::cerr << "Failed to catch expected exception " \ + << #EXCEPTION << "!" << std::endl; \ + /* This indicates a problem in the test that should be addressed. */ \ + throw; \ +} + +#endif // LL_LINUX + +#endif /* ! defined(LL_CATCH_AND_STORE_WHAT_IN_H) */ diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp index 4699bb1827..a9114075fc 100644 --- a/indra/test/llevents_tut.cpp +++ b/indra/test/llevents_tut.cpp @@ -49,46 +49,12 @@ #include <boost/assign/list_of.hpp> // other Linden headers #include "lltut.h" +#include "catch_and_store_what_in.h" #include "stringize.h" #include "tests/listener.h" using boost::assign::list_of; -#ifdef LL_LINUX -#define CATCH_MISSED_LINUX_EXCEPTION(exception, threw) \ -catch (const std::runtime_error& ex) \ -{ \ - /* This clause is needed on Linux, on the viewer side, because the */ \ - /* exception isn't caught by the clause above. Warn the user... */ \ - std::cerr << "Failed to catch " << typeid(ex).name() << std::endl; \ - /* But if the expected exception was thrown, allow the test to */ \ - /* succeed anyway. Not sure how else to handle this odd case. */ \ - /* This approach is also used in llsdmessage_test.cpp. */ \ - if (std::string(typeid(ex).name()) == typeid(exception).name()) \ - { \ - threw = ex.what(); \ - /*std::cout << ex.what() << std::endl;*/ \ - } \ - else \ - { \ - /* We don't even recognize this exception. Let it propagate */ \ - /* out to TUT to fail the test. */ \ - throw; \ - } \ -} \ -catch (...) \ -{ \ - std::cerr << "Utterly failed to catch expected exception " << #exception << "!" << \ - std::endl; \ - /* This indicates a problem in the test that should be addressed. */ \ - throw; \ -} - -#else // LL_LINUX -#define CATCH_MISSED_LINUX_EXCEPTION(exception, threw) \ - /* Not needed on other platforms */ -#endif // LL_LINUX - template<typename T> T make(const T& value) { @@ -178,11 +144,7 @@ void events_object::test<1>() per_frame.listen(listener0.getName(), // note bug, dup name boost::bind(&Listener::call, boost::ref(listener1), _1)); } - catch (const LLEventPump::DupListenerName& e) - { - threw = e.what(); - } - CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::DupListenerName, threw) + CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupListenerName) ensure_equals(threw, std::string("DupListenerName: " "Attempt to register duplicate listener name '") + @@ -354,7 +316,6 @@ void events_object::test<7>() { set_test_name("listener dependency order"); typedef LLEventPump::NameList NameList; - typedef Collect::StringList StringList; LLEventPump& button(pumps.obtain("button")); Collect collector; button.listen("Mary", @@ -368,7 +329,7 @@ void events_object::test<7>() button.listen("spot", boost::bind(&Collect::add, boost::ref(collector), "spot", _1)); button.post(1); - ensure_equals(collector.result, make<StringList>(list_of("spot")("checked")("Mary"))); + ensure_equals(collector.result, make<StringVec>(list_of("spot")("checked")("Mary"))); collector.clear(); button.stopListening("Mary"); button.listen("Mary", @@ -377,7 +338,7 @@ void events_object::test<7>() // now "Mary" must come before "spot" make<NameList>(list_of("spot"))); button.post(2); - ensure_equals(collector.result, make<StringList>(list_of("Mary")("spot")("checked"))); + ensure_equals(collector.result, make<StringVec>(list_of("Mary")("spot")("checked"))); collector.clear(); button.stopListening("spot"); std::string threw; @@ -388,12 +349,7 @@ void events_object::test<7>() // after "Mary" and "checked" -- whoops! make<NameList>(list_of("Mary")("checked"))); } - catch (const LLEventPump::Cycle& e) - { - threw = e.what(); - // std::cout << "Caught: " << e.what() << '\n'; - } - CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::Cycle, threw) + CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::Cycle) // Obviously the specific wording of the exception text can // change; go ahead and change the test to match. // Establish that it contains: @@ -416,7 +372,7 @@ void events_object::test<7>() boost::bind(&Collect::add, boost::ref(collector), "shoelaces", _1), make<NameList>(list_of("checked"))); button.post(3); - ensure_equals(collector.result, make<StringList>(list_of("Mary")("checked")("yellow")("shoelaces"))); + ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces"))); collector.clear(); threw.clear(); try @@ -426,12 +382,7 @@ void events_object::test<7>() make<NameList>(list_of("shoelaces")), make<NameList>(list_of("yellow"))); } - catch (const LLEventPump::OrderChange& e) - { - threw = e.what(); - // std::cout << "Caught: " << e.what() << '\n'; - } - CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::OrderChange, threw) + CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::OrderChange) // Same remarks about the specific wording of the exception. Just // ensure that it contains enough information to clarify the // problem and what must be done to resolve it. @@ -443,7 +394,7 @@ void events_object::test<7>() ensure_contains("old order", threw, "was: Mary, checked, yellow, shoelaces"); ensure_contains("new order", threw, "now: Mary, checked, shoelaces, of, yellow"); button.post(4); - ensure_equals(collector.result, make<StringList>(list_of("Mary")("checked")("yellow")("shoelaces"))); + ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces"))); } template<> template<> @@ -459,12 +410,7 @@ void events_object::test<8>() // then another with a duplicate name. LLEventStream bob2("bob"); } - catch (const LLEventPump::DupPumpName& e) - { - threw = e.what(); - // std::cout << "Caught: " << e.what() << '\n'; - } - CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::DupPumpName, threw) + CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName) ensure("Caught DupPumpName", !threw.empty()); } // delete first 'bob' LLEventStream bob("bob"); // should work, previous one unregistered @@ -505,11 +451,7 @@ void events_object::test<9>() LLListenerOrPumpName empty; empty(17); } - catch (const LLListenerOrPumpName::Empty& e) - { - threw = e.what(); - } - CATCH_MISSED_LINUX_EXCEPTION(LLListenerOrPumpName::Empty, threw) + CATCH_AND_STORE_WHAT_IN(threw, LLListenerOrPumpName::Empty) ensure("threw Empty", !threw.empty()); } diff --git a/indra/test/manageapr.h b/indra/test/manageapr.h new file mode 100644 index 0000000000..2452fb6ae4 --- /dev/null +++ b/indra/test/manageapr.h @@ -0,0 +1,46 @@ +/** + * @file manageapr.h + * @author Nat Goodspeed + * @date 2012-01-13 + * @brief ManageAPR class for simple test programs + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_MANAGEAPR_H) +#define LL_MANAGEAPR_H + +#include "llapr.h" +#include <boost/noncopyable.hpp> + +/** + * Declare a static instance of this class for dead-simple ll_init_apr() at + * program startup, ll_cleanup_apr() at termination. This is recommended for + * use only with simple test programs. Once you start introducing static + * instances of other classes that depend on APR already being initialized, + * the indeterminate static-constructor-order problem rears its ugly head. + */ +class ManageAPR: public boost::noncopyable +{ +public: + ManageAPR() + { + ll_init_apr(); + } + + ~ManageAPR() + { + ll_cleanup_apr(); + } + + static std::string strerror(apr_status_t rv) + { + char errbuf[256]; + apr_strerror(rv, errbuf, sizeof(errbuf)); + return errbuf; + } +}; + +#endif /* ! defined(LL_MANAGEAPR_H) */ diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h new file mode 100644 index 0000000000..6069064627 --- /dev/null +++ b/indra/test/namedtempfile.h @@ -0,0 +1,205 @@ +/** + * @file namedtempfile.h + * @author Nat Goodspeed + * @date 2012-01-13 + * @brief NamedTempFile class for tests that need disk files as fixtures. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_NAMEDTEMPFILE_H) +#define LL_NAMEDTEMPFILE_H + +#include "llerror.h" +#include "llapr.h" +#include "apr_file_io.h" +#include <string> +#include <boost/function.hpp> +#include <boost/lambda/lambda.hpp> +#include <boost/lambda/bind.hpp> +#include <boost/noncopyable.hpp> +#include <iostream> +#include <sstream> + +/** + * Create a text file with specified content "somewhere in the + * filesystem," cleaning up when it goes out of scope. + */ +class NamedTempFile: public boost::noncopyable +{ + LOG_CLASS(NamedTempFile); +public: + NamedTempFile(const std::string& pfx, const std::string& content, apr_pool_t* pool=gAPRPoolp): + mPool(pool) + { + createFile(pfx, boost::lambda::_1 << content); + } + + // Disambiguate when passing string literal + NamedTempFile(const std::string& pfx, const char* content, apr_pool_t* pool=gAPRPoolp): + mPool(pool) + { + createFile(pfx, boost::lambda::_1 << content); + } + + // Function that accepts an ostream ref and (presumably) writes stuff to + // it, e.g.: + // (boost::lambda::_1 << "the value is " << 17 << '\n') + typedef boost::function<void(std::ostream&)> Streamer; + + NamedTempFile(const std::string& pfx, const Streamer& func, apr_pool_t* pool=gAPRPoolp): + mPool(pool) + { + createFile(pfx, func); + } + + virtual ~NamedTempFile() + { + ll_apr_assert_status(apr_file_remove(mPath.c_str(), mPool)); + } + + virtual std::string getName() const { return mPath; } + + void peep() + { + std::cout << "File '" << mPath << "' contains:\n"; + std::ifstream reader(mPath.c_str()); + std::string line; + while (std::getline(reader, line)) + std::cout << line << '\n'; + std::cout << "---\n"; + } + +protected: + void createFile(const std::string& pfx, const Streamer& func) + { + // Create file in a temporary place. + const char* tempdir = NULL; + ll_apr_assert_status(apr_temp_dir_get(&tempdir, mPool)); + + // Construct a temp filename template in that directory. + char *tempname = NULL; + ll_apr_assert_status(apr_filepath_merge(&tempname, + tempdir, + (pfx + "XXXXXX").c_str(), + 0, + mPool)); + + // Create a temp file from that template. + apr_file_t* fp = NULL; + ll_apr_assert_status(apr_file_mktemp(&fp, + tempname, + APR_CREATE | APR_WRITE | APR_EXCL, + mPool)); + // apr_file_mktemp() alters tempname with the actual name. Not until + // now is it valid to capture as our mPath. + mPath = tempname; + + // Write desired content. + std::ostringstream out; + // Stream stuff to it. + func(out); + + std::string data(out.str()); + apr_size_t writelen(data.length()); + ll_apr_assert_status(apr_file_write(fp, data.c_str(), &writelen)); + ll_apr_assert_status(apr_file_close(fp)); + llassert_always(writelen == data.length()); + } + + std::string mPath; + apr_pool_t* mPool; +}; + +/** + * Create a NamedTempFile with a specified filename extension. This is useful + * when, for instance, you must be able to use the file in a Python import + * statement. + * + * A NamedExtTempFile actually has two different names. We retain the original + * no-extension name as a placeholder in the temp directory to ensure + * uniqueness; to that we link the name plus the desired extension. Naturally, + * both must be removed on destruction. + */ +class NamedExtTempFile: public NamedTempFile +{ + LOG_CLASS(NamedExtTempFile); +public: + NamedExtTempFile(const std::string& ext, const std::string& content, apr_pool_t* pool=gAPRPoolp): + NamedTempFile(remove_dot(ext), content, pool), + mLink(mPath + ensure_dot(ext)) + { + linkto(mLink); + } + + // Disambiguate when passing string literal + NamedExtTempFile(const std::string& ext, const char* content, apr_pool_t* pool=gAPRPoolp): + NamedTempFile(remove_dot(ext), content, pool), + mLink(mPath + ensure_dot(ext)) + { + linkto(mLink); + } + + NamedExtTempFile(const std::string& ext, const Streamer& func, apr_pool_t* pool=gAPRPoolp): + NamedTempFile(remove_dot(ext), func, pool), + mLink(mPath + ensure_dot(ext)) + { + linkto(mLink); + } + + virtual ~NamedExtTempFile() + { + ll_apr_assert_status(apr_file_remove(mLink.c_str(), mPool)); + } + + // Since the caller has gone to the trouble to create the name with the + // extension, that should be the name we return. In this class, mPath is + // just a placeholder to ensure that future createFile() calls won't + // collide. + virtual std::string getName() const { return mLink; } + + static std::string ensure_dot(const std::string& ext) + { + if (ext.empty()) + { + // What SHOULD we do when the caller makes a point of using + // NamedExtTempFile to generate a file with a particular + // extension, then passes an empty extension? Use just "."? That + // sounds like a Bad Idea, especially on Windows. Treat that as a + // coding error. + LL_ERRS("NamedExtTempFile") << "passed empty extension" << LL_ENDL; + } + if (ext[0] == '.') + { + return ext; + } + return std::string(".") + ext; + } + + static std::string remove_dot(const std::string& ext) + { + std::string::size_type found = ext.find_first_not_of("."); + if (found == std::string::npos) + { + return ext; + } + return ext.substr(found); + } + +private: + void linkto(const std::string& path) + { + // This method assumes that since mPath (without extension) is + // guaranteed by apr_file_mktemp() to be unique, then (mPath + any + // extension) is also unique. This is likely, though not guaranteed: + // files could be created in the same temp directory other than by + // this class. + ll_apr_assert_status(apr_file_link(mPath.c_str(), path.c_str())); + } + + std::string mLink; +}; + +#endif /* ! defined(LL_NAMEDTEMPFILE_H) */ diff --git a/indra/test/test.cpp b/indra/test/test.cpp index ffdb0cb976..9d24383bcc 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -37,6 +37,9 @@ #include "linden_common.h" #include "llerrorcontrol.h" #include "lltut.h" +#include "tests/wrapllerrs.h" // RecorderProxy +#include "stringize.h" +#include "namedtempfile.h" #include "apr_pools.h" #include "apr_getopt.h" @@ -53,24 +56,122 @@ #include <gtest/gtest.h> #endif +#if LL_MSVC +#pragma warning (push) +#pragma warning (disable : 4702) // warning C4702: unreachable code +#endif +#include <boost/iostreams/tee.hpp> +#include <boost/iostreams/stream.hpp> +#if LL_MSVC +#pragma warning (pop) +#endif + +#include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/make_shared.hpp> +#include <boost/foreach.hpp> +#include <boost/lambda/lambda.hpp> + +#include <fstream> + +void wouldHaveCrashed(const std::string& message); + namespace tut { std::string sSourceDir; - - test_runner_singleton runner; + + test_runner_singleton runner; } +class LLReplayLog +{ +public: + LLReplayLog() {} + virtual ~LLReplayLog() {} + + virtual void reset() {} + virtual void replay(std::ostream&) {} +}; + +class LLReplayLogReal: public LLReplayLog, public LLError::Recorder, public boost::noncopyable +{ +public: + LLReplayLogReal(LLError::ELevel level, apr_pool_t* pool): + mOldSettings(LLError::saveAndResetSettings()), + mProxy(new RecorderProxy(this)), + mTempFile("log", "", pool), // create file + mFile(mTempFile.getName().c_str()) // open it + { + LLError::setFatalFunction(wouldHaveCrashed); + LLError::setDefaultLevel(level); + LLError::addRecorder(mProxy); + } + + virtual ~LLReplayLogReal() + { + LLError::removeRecorder(mProxy); + delete mProxy; + LLError::restoreSettings(mOldSettings); + } + + virtual void recordMessage(LLError::ELevel level, const std::string& message) + { + mFile << message << std::endl; + } + + virtual void reset() + { + mFile.close(); + mFile.open(mTempFile.getName().c_str()); + } + + virtual void replay(std::ostream& out) + { + mFile.close(); + std::ifstream inf(mTempFile.getName().c_str()); + std::string line; + while (std::getline(inf, line)) + { + out << line << std::endl; + } + } + +private: + LLError::Settings* mOldSettings; + LLError::Recorder* mProxy; + NamedTempFile mTempFile; + std::ofstream mFile; +}; + class LLTestCallback : public tut::callback { public: - LLTestCallback(bool verbose_mode, std::ostream *stream) : - mVerboseMode(verbose_mode), - mTotalTests(0), - mPassedTests(0), - mFailedTests(0), - mSkippedTests(0), - mStream(stream) + LLTestCallback(bool verbose_mode, std::ostream *stream, + boost::shared_ptr<LLReplayLog> replayer) : + mVerboseMode(verbose_mode), + mTotalTests(0), + mPassedTests(0), + mFailedTests(0), + mSkippedTests(0), + // By default, capture a shared_ptr to std::cout, with a no-op "deleter" + // so that destroying the shared_ptr makes no attempt to delete std::cout. + mStream(boost::shared_ptr<std::ostream>(&std::cout, boost::lambda::_1)), + mReplayer(replayer) { + if (stream) + { + // We want a boost::iostreams::tee_device that will stream to two + // std::ostreams. + typedef boost::iostreams::tee_device<std::ostream, std::ostream> TeeDevice; + // More than that, though, we want an actual stream using that + // device. + typedef boost::iostreams::stream<TeeDevice> TeeStream; + // Allocate and assign in two separate steps, per Herb Sutter. + // (Until we turn on C++11 support, have to wrap *stream with + // boost::ref() due to lack of perfect forwarding.) + boost::shared_ptr<std::ostream> pstream(new TeeStream(std::cout, boost::ref(*stream))); + mStream = pstream; + } } ~LLTestCallback() @@ -83,18 +184,31 @@ public: } virtual void group_started(const std::string& name) { - std::cout << "Unit test group_started name=" << name << std::endl; + *mStream << "Unit test group_started name=" << name << std::endl; } virtual void group_completed(const std::string& name) { - std::cout << "Unit test group_completed name=" << name << std::endl; + *mStream << "Unit test group_completed name=" << name << std::endl; } virtual void test_completed(const tut::test_result& tr) { ++mTotalTests; + + // If this test failed, dump requested log messages BEFORE stating the + // test result. + if (tr.result != tut::test_result::ok && tr.result != tut::test_result::skip) + { + mReplayer->replay(*mStream); + } + // Either way, clear stored messages in preparation for next test. + mReplayer->reset(); + std::ostringstream out; - out << "[" << tr.group << ", " << tr.test << "] "; + out << "[" << tr.group << ", " << tr.test; + if (! tr.name.empty()) + out << ": " << tr.name; + out << "] "; switch(tr.result) { case tut::test_result::ok: @@ -123,56 +237,43 @@ public: break; default: ++mFailedTests; - out << "unknown"; + out << "unknown (tr.result == " << tr.result << ")"; } if(mVerboseMode || (tr.result != tut::test_result::ok)) { + *mStream << out.str(); if(!tr.message.empty()) { - out << ": '" << tr.message << "'"; + *mStream << ": '" << tr.message << "'"; } - if (mStream) - { - *mStream << out.str() << std::endl; - } - - std::cout << out.str() << std::endl; - } - } - - virtual void run_completed() - { - if (mStream) - { - run_completed_(*mStream); + *mStream << std::endl; } - run_completed_(std::cout); } virtual int getFailedTests() const { return mFailedTests; } - virtual void run_completed_(std::ostream &stream) + virtual void run_completed() { - stream << "\tTotal Tests:\t" << mTotalTests << std::endl; - stream << "\tPassed Tests:\t" << mPassedTests; + *mStream << "\tTotal Tests:\t" << mTotalTests << std::endl; + *mStream << "\tPassed Tests:\t" << mPassedTests; if (mPassedTests == mTotalTests) { - stream << "\tYAY!! \\o/"; + *mStream << "\tYAY!! \\o/"; } - stream << std::endl; + *mStream << std::endl; if (mSkippedTests > 0) { - stream << "\tSkipped known failures:\t" << mSkippedTests + *mStream << "\tSkipped known failures:\t" << mSkippedTests << std::endl; } if(mFailedTests > 0) { - stream << "*********************************" << std::endl; - stream << "Failed Tests:\t" << mFailedTests << std::endl; - stream << "Please report or fix the problem." << std::endl; - stream << "*********************************" << std::endl; + *mStream << "*********************************" << std::endl; + *mStream << "Failed Tests:\t" << mFailedTests << std::endl; + *mStream << "Please report or fix the problem." << std::endl; + *mStream << "*********************************" << std::endl; } } @@ -182,7 +283,8 @@ protected: int mPassedTests; int mFailedTests; int mSkippedTests; - std::ostream *mStream; + boost::shared_ptr<std::ostream> mStream; + boost::shared_ptr<LLReplayLog> mReplayer; }; // TeamCity specific class which emits service messages @@ -191,85 +293,113 @@ protected: class LLTCTestCallback : public LLTestCallback { public: - LLTCTestCallback(bool verbose_mode, std::ostream *stream) : - LLTestCallback(verbose_mode, stream), - mTCStream() + LLTCTestCallback(bool verbose_mode, std::ostream *stream, + boost::shared_ptr<LLReplayLog> replayer) : + LLTestCallback(verbose_mode, stream, replayer) { } ~LLTCTestCallback() { - } + } virtual void group_started(const std::string& name) { LLTestCallback::group_started(name); - mTCStream << "\n##teamcity[testSuiteStarted name='" << name << "']" << std::endl; + std::cout << "\n##teamcity[testSuiteStarted name='" << escape(name) << "']" << std::endl; } virtual void group_completed(const std::string& name) { LLTestCallback::group_completed(name); - mTCStream << "##teamcity[testSuiteFinished name='" << name << "']" << std::endl; + std::cout << "##teamcity[testSuiteFinished name='" << escape(name) << "']" << std::endl; } virtual void test_completed(const tut::test_result& tr) { + std::string testname(STRINGIZE(tr.group << "." << tr.test)); + if (! tr.name.empty()) + { + testname.append(":"); + testname.append(tr.name); + } + testname = escape(testname); + + // Sadly, tut::callback doesn't give us control at test start; have to + // backfill start message into TC output. + std::cout << "##teamcity[testStarted name='" << testname << "']" << std::endl; + + // now forward call to base class so any output produced there is in + // the right TC context LLTestCallback::test_completed(tr); switch(tr.result) { case tut::test_result::ok: - mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; - mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; break; + case tut::test_result::fail: - mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; - mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl; - mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; - break; case tut::test_result::ex: - mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; - mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl; - mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; - break; case tut::test_result::warn: - mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; - mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl; - mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; - break; case tut::test_result::term: - mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; - mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl; - mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; + std::cout << "##teamcity[testFailed name='" << testname + << "' message='" << escape(tr.message) << "']" << std::endl; break; + case tut::test_result::skip: - mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; - mTCStream << "##teamcity[testIgnored name='" << tr.group << "." << tr.test << "']" << std::endl; - mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; + std::cout << "##teamcity[testIgnored name='" << testname << "']" << std::endl; break; + default: break; } + std::cout << "##teamcity[testFinished name='" << testname << "']" << std::endl; } - virtual void run_completed() - { - LLTestCallback::run_completed(); - - // dump the TC reporting results to cout - tc_run_completed_(std::cout); - } - - virtual void tc_run_completed_(std::ostream &stream) + static std::string escape(const std::string& str) { - - // dump the TC reporting results to cout - stream << mTCStream.str() << std::endl; + // Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages + std::string result; + BOOST_FOREACH(char c, str) + { + switch (c) + { + case '\'': + result.append("|'"); + break; + case '\n': + result.append("|n"); + break; + case '\r': + result.append("|r"); + break; +/*==========================================================================*| + // These are not possible 'char' values from a std::string. + case '\u0085': // next line + result.append("|x"); + break; + case '\u2028': // line separator + result.append("|l"); + break; + case '\u2029': // paragraph separator + result.append("|p"); + break; +|*==========================================================================*/ + case '|': + result.append("||"); + break; + case '[': + result.append("|["); + break; + case ']': + result.append("|]"); + break; + default: + result.push_back(c); + break; + } + } + return result; } - -protected: - std::ostringstream mTCStream; - }; @@ -306,6 +436,14 @@ void stream_usage(std::ostream& s, const char* app) ++option; } + s << app << " is also sensitive to environment variables:\n" + << "LOGTEST=level : for all tests, emit log messages at level 'level'\n" + << "LOGFAIL=level : only for failed tests, emit log messages at level 'level'\n" + << "where 'level' is one of ALL, DEBUG, INFO, WARN, ERROR, NONE.\n" + << "--debug is like LOGTEST=DEBUG, but --debug overrides LOGTEST.\n" + << "Setting LOGFAIL overrides both LOGTEST and --debug: the only log\n" + << "messages you will see will be for failed tests.\n\n"; + s << "Examples:" << std::endl; s << " " << app << " --verbose" << std::endl; s << "\tRun all the tests and report all results." << std::endl; @@ -342,8 +480,14 @@ int main(int argc, char **argv) LLError::initForApplication("."); LLError::setFatalFunction(wouldHaveCrashed); LLError::setDefaultLevel(LLError::LEVEL_ERROR); - //< *TODO: should come from error config file. Note that we - // have a command line option that sets this to debug. + // ^ possibly overridden by --debug, LOGTEST or LOGFAIL + + // LOGTEST overrides default, but can be overridden by --debug or LOGFAIL. + const char* LOGTEST = getenv("LOGTEST"); + if (LOGTEST) + { + LLError::setDefaultLevel(LLError::decodeLevel(LOGTEST)); + } #ifdef CTYPE_WORKAROUND ctype_workaround(); @@ -359,7 +503,7 @@ int main(int argc, char **argv) apr_getopt_t* os = NULL; if(APR_SUCCESS != apr_getopt_init(&os, pool, argc, argv)) { - std::cerr << "Unable to pool" << std::endl; + std::cerr << "apr_getopt_init() failed" << std::endl; return 1; } @@ -373,7 +517,7 @@ int main(int argc, char **argv) apr_status_t apr_err; const char* opt_arg = NULL; int opt_id = 0; - std::ofstream *output = NULL; + boost::scoped_ptr<std::ofstream> output; const char *touch = NULL; while(true) @@ -403,7 +547,7 @@ int main(int argc, char **argv) verbose_mode = true; break; case 'o': - output = new std::ofstream; + output.reset(new std::ofstream); output->open(opt_arg); break; case 's': // --sourcedir @@ -418,8 +562,6 @@ int main(int argc, char **argv) wait_at_exit = true; break; case 'd': - // *TODO: should come from error config file. We set it to - // ERROR by default, so this allows full debug levels. LLError::setDefaultLevel(LLError::LEVEL_DEBUG); break; case 'x': @@ -434,14 +576,28 @@ int main(int argc, char **argv) // run the tests + const char* LOGFAIL = getenv("LOGFAIL"); + boost::shared_ptr<LLReplayLog> replayer; + // As described in stream_usage(), LOGFAIL overrides both --debug and + // LOGTEST. + if (LOGFAIL) + { + LLError::ELevel level = LLError::decodeLevel(LOGFAIL); + replayer.reset(new LLReplayLogReal(level, pool)); + } + else + { + replayer.reset(new LLReplayLog()); + } + LLTestCallback* mycallback; if (getenv("TEAMCITY_PROJECT_NAME")) { - mycallback = new LLTCTestCallback(verbose_mode, output); + mycallback = new LLTCTestCallback(verbose_mode, output.get(), replayer); } else { - mycallback = new LLTestCallback(verbose_mode, output); + mycallback = new LLTestCallback(verbose_mode, output.get(), replayer); } tut::runner.get().set_callback(mycallback); @@ -463,12 +619,6 @@ int main(int argc, char **argv) std::cin.get(); } - if (output) - { - output->close(); - delete output; - } - if (touch && success) { std::ofstream s; diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 19ac418e9e..75e455e3f6 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -1,24 +1,24 @@ -/** +/** * @file llupdatedownloader.cpp * * $LicenseInfo:firstyear=2010&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$ */ @@ -58,7 +58,7 @@ public: int onProgress(double downloadSize, double bytesDownloaded); void resume(void); void setBandwidthLimit(U64 bytesPerSecond); - + private: curl_off_t mBandwidthLimit; bool mCancelled; @@ -69,7 +69,7 @@ private: unsigned char mDownloadPercent; std::string mDownloadRecordPath; curl_slist * mHeaderList; - + void initializeCurlGet(std::string const & url, bool processHeader); void resumeDownloading(size_t startByte); void run(void); @@ -93,7 +93,7 @@ namespace { } }; - + const char * gSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml"; }; @@ -192,18 +192,18 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & mHeaderList(0) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. - llverify(code == CURLE_OK); // TODO: real error handling here. + llverify(code == CURLE_OK); // TODO: real error handling here. } LLUpdateDownloader::Implementation::~Implementation() { - if(isDownloading()) + if(isDownloading()) { cancel(); shutdown(); - } - else + } + else { ; // No op. } @@ -218,7 +218,7 @@ void LLUpdateDownloader::Implementation::cancel(void) { mCancelled = true; } - + void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash, @@ -259,24 +259,24 @@ void LLUpdateDownloader::Implementation::resume(void) mClient.downloadError("no download marker"); return; } - + LLSDSerialize::fromXMLDocument(mDownloadData, dataStream); - + if(!mDownloadData.asBoolean()) { mClient.downloadError("no download information in marker"); return; } - + std::string filePath = mDownloadData["path"].asString(); try { - if(LLFile::isfile(filePath)) { + if(LLFile::isfile(filePath)) { llstat fileStatus; LLFile::stat(filePath, &fileStatus); if(fileStatus.st_size != mDownloadData["size"].asInteger()) { resumeDownloading(fileStatus.st_size); } else if(!validateDownload()) { LLFile::remove(filePath); - download(LLURI(mDownloadData["url"].asString()), + download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), mDownloadData["update_version"].asString(), mDownloadData["required"].asBoolean()); @@ -284,7 +284,7 @@ void LLUpdateDownloader::Implementation::resume(void) mClient.downloadComplete(mDownloadData); } } else { - download(LLURI(mDownloadData["url"].asString()), + download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), mDownloadData["update_version"].asString(), mDownloadData["required"].asBoolean()); @@ -301,7 +301,7 @@ void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) llassert(mCurl != 0); mBandwidthLimit = bytesPerSecond; CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); - if(code != CURLE_OK) LL_WARNS("UpdateDownload") << + if(code != CURLE_OK) LL_WARNS("UpdateDownload") << "unable to change dowload bandwidth" << LL_ENDL; } else { mBandwidthLimit = bytesPerSecond; @@ -315,7 +315,7 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) std::string header(headerPtr, headerPtr + size); size_t colonPosition = header.find(':'); if(colonPosition == std::string::npos) return size; // HTML response; ignore. - + if(header.substr(0, colonPosition) == "Content-Length") { try { size_t firstDigitPos = header.find_first_of("0123456789", colonPosition); @@ -323,18 +323,18 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1); size_t size = boost::lexical_cast<size_t>(contentLength); LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL; - + mDownloadData["size"] = LLSD(LLSD::Integer(size)); llofstream odataStream(mDownloadRecordPath); LLSDSerialize::toPrettyXML(mDownloadData, odataStream); } catch (std::exception const & e) { - LL_WARNS("UpdateDownload") << "unable to read content length (" + LL_WARNS("UpdateDownload") << "unable to read content length (" << e.what() << ")" << LL_ENDL; } } else { ; // No op. } - + return size; } @@ -342,9 +342,9 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) { if(mCancelled) return 0; // Forces a write error which will halt curl thread. - if((size == 0) || (buffer == 0)) return 0; - - mDownloadStream.write(reinterpret_cast<const char *>(buffer), size); + if((size == 0) || (buffer == 0)) return 0; + + mDownloadStream.write(static_cast<const char *>(buffer), size); if(mDownloadStream.bad()) { return 0; } else { @@ -358,7 +358,7 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b int downloadPercent = static_cast<int>(100. * (bytesDownloaded / downloadSize)); if(downloadPercent > mDownloadPercent) { mDownloadPercent = downloadPercent; - + LLSD event; event["pump"] = LLUpdaterService::pumpName(); LLSD payload; @@ -367,12 +367,12 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b payload["bytes_downloaded"] = bytesDownloaded; event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); - + LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL; } else { ; // Keep events to a reasonalbe number. } - + return 0; } @@ -396,13 +396,13 @@ void LLUpdateDownloader::Implementation::run(void) LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL; // Do not call back client. } else { - LL_WARNS("UpdateDownload") << "download failed with error '" << + LL_WARNS("UpdateDownload") << "download failed with error '" << curl_easy_strerror(code) << "'" << LL_ENDL; LLFile::remove(mDownloadRecordPath); if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString()); mClient.downloadError("curl error"); } - + if(mHeaderList) { curl_slist_free_all(mHeaderList); mHeaderList = 0; @@ -412,17 +412,17 @@ void LLUpdateDownloader::Implementation::run(void) void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader) { - if(mCurl == 0) + if(mCurl == 0) { mCurl = LLCurl::newEasyHandle(); - } - else + } + else { curl_easy_reset(mCurl); } - + if(mCurl == 0) throw DownloadError("failed to initialize curl"); - + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function)); @@ -439,7 +439,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u // if it's a required update set the bandwidth limit to 0 (unlimited) curl_off_t limit = mDownloadData["required"].asBoolean() ? 0 : mBandwidthLimit; throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, limit)); - + mDownloadPercent = 0; } @@ -450,7 +450,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) << " at byte " << startByte << LL_ENDL; initializeCurlGet(mDownloadData["url"].asString(), false); - + // The header 'Range: bytes n-' will request the bytes remaining in the // source begining with byte n and ending with the last byte. boost::format rangeHeaderFormat("Range: bytes=%u-"); @@ -458,7 +458,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str()); if(mHeaderList == 0) throw DownloadError("cannot add Range header"); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList)); - + mDownloadStream.open(mDownloadData["path"].asString(), std::ios_base::out | std::ios_base::binary | std::ios_base::app); start(); @@ -479,10 +479,10 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std LL_INFOS("UpdateDownload") << "downloading " << filePath << " from " << uri.asString() << LL_ENDL; LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL; - + llofstream dataStream(mDownloadRecordPath); LLSDSerialize::toPrettyXML(mDownloadData, dataStream); - + mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary); initializeCurlGet(uri.asString(), true); start(); diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index c7b70c2de8..2f87d59373 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -26,10 +26,10 @@ #include "linden_common.h" #include <apr_file_io.h> #include "llapr.h" -#include "llprocesslauncher.h" +#include "llprocess.h" #include "llupdateinstaller.h" #include "lldir.h" - +#include "llsd.h" #if defined(LL_WINDOWS) #pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!). @@ -78,15 +78,13 @@ int ll_install_update(std::string const & script, llinfos << "UpdateInstaller: installing " << updatePath << " using " << actualScriptPath << LL_ENDL; - LLProcessLauncher launcher; - launcher.setExecutable(actualScriptPath); - launcher.addArgument(updatePath); - launcher.addArgument(ll_install_failed_marker_path().c_str()); - launcher.addArgument(boost::lexical_cast<std::string>(required)); - int result = launcher.launch(); - launcher.orphan(); - - return result; + LLProcess::Params params; + params.executable = actualScriptPath; + params.args.add(updatePath); + params.args.add(ll_install_failed_marker_path()); + params.args.add(boost::lexical_cast<std::string>(required)); + params.autokill = false; + return LLProcess::create(params)? 0 : -1; } diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 1888f191e2..2e18218667 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -447,7 +447,7 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds) LL_INFOS("UpdaterService") << "will check for update again in " << seconds << " seconds" << LL_ENDL; mTimer.start(); - mTimer.setTimerExpirySec(seconds); + mTimer.setTimerExpirySec((F32)seconds); LLEventPumps::instance().obtain("mainloop").listen( sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1)); } |