diff options
Diffstat (limited to 'indra/newview')
162 files changed, 2403 insertions, 1307 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index edeac085c2..73b234eb75 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1751,6 +1751,10 @@ endif (HAVOK OR HAVOK_TPV)  # progress view disables/enables icons based on available packages  set_source_files_properties(llprogressview.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") +if (GLODLIB) +  set_source_files_properties(llfloatermodelpreview.cpp PROPERTIES COMPILE_FLAGS "-DLL_GLOD") +endif (GLODLIB) +  list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES})  set_source_files_properties(${viewer_HEADER_FILES} diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index ef25c648a7..fbff8fe307 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -340,7 +340,7 @@  				<string key="NSMaxSize">{10000000000000, 10000000000000}</string>  				<string key="NSFrameAutosaveName">Second Life</string>  				<int key="NSWindowCollectionBehavior">128</int> -				<bool key="NSWindowIsRestorable">YES</bool> +				<bool key="NSWindowIsRestorable">NO</bool>  			</object>  			<object class="NSWindowTemplate" id="979091056">  				<int key="NSWindowStyleMask">31</int> diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 826f5ce030..54358db763 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.0 +6.5.4 diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index 4f6deb1f98..1a5157838c 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -126,7 +126,6 @@      <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>      <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/> -    <binding key="" mask="NONE" mouse="LMB" command="walk_to"/>    </third_person>    <sitting>      <binding key="A" mask="ALT" command="spin_around_cw"/> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 43e554e532..bb83824628 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8352,7 +8352,7 @@      <key>PushToTalkToggle</key>      <map>        <key>Comment</key> -      <string>Should the push-to-talk button behave as a toggle</string> +      <string>Should the push-to-talk toolbar button behave as a toggle</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -8396,7 +8396,18 @@      <key>QAModeMetrics</key>      <map>        <key>Comment</key> -      <string>"Enables QA features (logging, faster cycling) for metrics collector"</string> +      <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>QAModeFakeSystemFolderIssues</key> +    <map> +      <key>Comment</key> +      <string>Simulates system folder issues in inventory</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -12579,6 +12590,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>TextureFetchMinTimeToLog</key> +    <map> +      <key>Comment</key> +      <string>If texture fetching time exceeds this value, texture fetch tester will log info</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>F32</string> +      <key>Value</key> +      <real>2.0</real> +    </map>    <key>TextureFetchFakeFailureRate</key>    <map>      <key>Comment</key> @@ -12667,6 +12689,17 @@        <key>Value</key>        <integer>32</integer>      </map> +    <key>TextureListFetchingThreshold</key> +    <map> +      <key>Comment</key> +      <string>If the ratio between fetched and all textures in the list is greater than this threshold, which we assume that almost all textures are fetched</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>F32</string> +      <key>Value</key> +      <real>0.97</real> +    </map>      <key>TextureLoadFullRes</key>      <map>        <key>Comment</key> diff --git a/indra/newview/build_win32_appConfig.py b/indra/newview/build_win32_appConfig.py index 9fdceee1be..d18d7b88cb 100755 --- a/indra/newview/build_win32_appConfig.py +++ b/indra/newview/build_win32_appConfig.py @@ -38,7 +38,7 @@ def munge_binding_redirect_version(src_manifest_name, src_config_name, dst_confi      comment = config_dom.createComment("This file is automatically generated by the build. see indra/newview/build_win32_appConfig.py")      config_dom.insertBefore(comment, config_dom.childNodes[0]) -    print "Writing: " + dst_config_name +    print("Writing: " + dst_config_name)      f = open(dst_config_name, 'w')      config_dom.writexml(f)      f.close() diff --git a/indra/newview/cursors_mac/UI_CURSOR_SIZEALL.tif b/indra/newview/cursors_mac/UI_CURSOR_SIZEALL.tifBinary files differ new file mode 100644 index 0000000000..85fec76fca --- /dev/null +++ b/indra/newview/cursors_mac/UI_CURSOR_SIZEALL.tif diff --git a/indra/newview/cursors_mac/UI_CURSOR_TOOLZOOMOUT.tif b/indra/newview/cursors_mac/UI_CURSOR_TOOLZOOMOUT.tifBinary files differ new file mode 100644 index 0000000000..d64a7f2b68 --- /dev/null +++ b/indra/newview/cursors_mac/UI_CURSOR_TOOLZOOMOUT.tif diff --git a/indra/newview/installers/darwin/apple-notarize.sh b/indra/newview/installers/darwin/apple-notarize.sh index e019437924..d90772ec0e 100755 --- a/indra/newview/installers/darwin/apple-notarize.sh +++ b/indra/newview/installers/darwin/apple-notarize.sh @@ -5,12 +5,12 @@ if [[ $SKIP_NOTARIZATION == "true" ]]; then  fi  CONFIG_FILE="$build_secrets_checkout/code-signing-osx/notarize_creds.sh" -if [ -f "$CONFIG_FILE" ]; then -    source $CONFIG_FILE +if [[ -f "$CONFIG_FILE" ]]; then +    source "$CONFIG_FILE"      app_file="$1"      zip_file=${app_file/app/zip}      ditto -c -k --keepParent "$app_file" "$zip_file" -    if [ -f "$zip_file" ]; then +    if [[ -f "$zip_file" ]]; then          res=$(xcrun altool --notarize-app --primary-bundle-id "com.secondlife.viewer" \                                     --username $USERNAME \                                     --password $PASSWORD \ @@ -19,37 +19,39 @@ if [ -f "$CONFIG_FILE" ]; then          echo $res          requestUUID=$(echo $res | awk '/RequestUUID/ { print $NF; }') -        echo "Apple Notarization RequestUUID: $requestUUID" -          if [[ -n $requestUUID ]]; then -            status="in progress" -            while [[ "$status" == "in progress" ]]; do +            in_progress=1 +            while [[ $in_progress -eq 1 ]]; do                  sleep 30 -                status=$(xcrun altool --notarization-info "$requestUUID" \ +                res=$(xcrun altool --notarization-info "$requestUUID" \                                              --username $USERNAME \ -                                            --password $PASSWORD 2>&1 \ -                                | awk -F ': ' '/Status:/ { print $2; }' ) -                echo "$status" +                                            --password $PASSWORD 2>&1) +                if [[ $res != *"in progress"* ]]; then  +                    in_progress=0 +                fi +                echo "."              done              # log results -            xcrun altool --notarization-info "$requestUUID" \ -                        --username $USERNAME \ -                        --password $PASSWORD +            echo $res              #remove temporary file              rm "$zip_file" -            if [["$status" == "success"]]; then +            if [[ $res == *"success"* ]]; then                  xcrun stapler staple "$app_file" -            elif [["$status" == "invalid"]]; then +                exit 0 +            elif [[ $res == *"invalid"* ]]; then                  echo "Notarization error: failed to process the app file"                  exit 1 +            else +                echo "Notarization error: unknown response status"              fi          else              echo "Notarization error: couldn't get request UUID" -            echo $res              exit 1          fi +    else +        echo "Notarization error: ditto failed" +        exit 1      fi  fi - diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 8838b6d0be..7513908cb4 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -561,10 +561,17 @@ Function CloseSecondLife    LOOP:
  	  FindWindow $0 "Second Life" ""
 -	  IntCmp $0 0 DONE
 +	  IntCmp $0 0 SLEEP
  	  Sleep 500
  	  Goto LOOP
 -
 +	  
 +  SLEEP:
 +    # Second life window just closed, but program might not be fully done yet
 +    # and OS might have not released some locks, wait a bit more to make sure
 +    # all file handles were released.
 +	# If something still isn't unlocked, it will trigger a notification from
 +	# RemoveProgFilesOnInst
 +    Sleep 1000
    DONE:
      Pop $0
      Return
 @@ -605,6 +612,18 @@ FunctionEnd  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  Function RemoveProgFilesOnInst
 +# We do not remove whole pervious install folder on install, since
 +# there is a chance that viewer was installed into some important
 +# folder by intent or accident
 +# RMDir /r $INSTDIR is especially unsafe if user installed somewhere
 +# like Program Files
 +
 +# Set retry counter. All integers are strings.
 +Push $0
 +StrCpy $0 0
 +
 +PREINSTALLREMOVE:
 +
  # Remove old SecondLife.exe to invalidate any old shortcuts to it that may be in non-standard locations. See MAINT-3575
  Delete "$INSTDIR\$INSTEXE"
  Delete "$INSTDIR\$VIEWER_EXE"
 @@ -612,13 +631,35 @@ Delete "$INSTDIR\$VIEWER_EXE"  # Remove old shader files first so fallbacks will work. See DEV-5663
  RMDir /r "$INSTDIR\app_settings\shaders"
 -# Remove skins folder to clean up files removed during development
 +# Remove folders to clean up files removed during development
 +RMDir /r "$INSTDIR\app_settings"
  RMDir /r "$INSTDIR\skins"
 +RMDir /r "$INSTDIR\vmp_icons"
 +
 +# Remove llplugin, plugins can crash or malfunction if they
 +# find modules from different versions
 +RMDir /r "$INSTDIR\llplugin"
 +
 +IntOp $0 $0 + 1
 +
 +IfErrors 0 PREINSTALLDONE
 +  IntCmp $0 1 PREINSTALLREMOVE #try again once
 +    StrCmp $SKIP_DIALOGS "true" PREINSTALLDONE
 +      MessageBox MB_ABORTRETRYIGNORE $(CloseSecondLifeInstRM) IDABORT PREINSTALLFAIL IDRETRY PREINSTALLREMOVE
 +      # MB_ABORTRETRYIGNORE does not accept IDIGNORE
 +      Goto PREINSTALLDONE
 +
 +PREINSTALLFAIL:
 +    Quit
 +
 +PREINSTALLDONE:
  # We are no longer including release notes with the viewer, so remove them.
  Delete "$SMPROGRAMS\$INSTSHORTCUT\SL Release Notes.lnk"
  Delete "$INSTDIR\releasenotes.txt"
 +Pop $0
 +
  FunctionEnd
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 diff --git a/indra/newview/installers/windows/lang_da.nsi b/indra/newview/installers/windows/lang_da.nsiBinary files differ index f462c82078..648ddbfb85 100644 --- a/indra/newview/installers/windows/lang_da.nsi +++ b/indra/newview/installers/windows/lang_da.nsi diff --git a/indra/newview/installers/windows/lang_de.nsi b/indra/newview/installers/windows/lang_de.nsi index eebcf027a8..188c30197a 100755 --- a/indra/newview/installers/windows/lang_de.nsi +++ b/indra/newview/installers/windows/lang_de.nsi @@ -64,6 +64,7 @@ LangString MissingSSE2 ${LANG_GERMAN} "Dieses Gerät verfügt möglicherweise ni  ; closesecondlife function (install)
  LangString CloseSecondLifeInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Second Life ..."
  LangString CloseSecondLifeInstMB ${LANG_GERMAN} "Second Life kann nicht installiert oder ersetzt werden, wenn es bereits läuft.$\n$\nBeenden Sie, was Sie gerade tun und klicken Sie OK, um Second Life zu beenden.$\nKlicken Sie CANCEL, um die Installation abzubrechen."
 +LangString CloseSecondLifeInstRM ${LANG_GERMAN} "Second Life failed to remove some files from a previous install."
  ; closesecondlife function (uninstall)
  LangString CloseSecondLifeUnInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Second Life ..."
 diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsiBinary files differ index ea680f08e4..0639d51e10 100644 --- a/indra/newview/installers/windows/lang_en-us.nsi +++ b/indra/newview/installers/windows/lang_en-us.nsi diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsiBinary files differ index 8a81110069..ee30651a38 100755 --- a/indra/newview/installers/windows/lang_es.nsi +++ b/indra/newview/installers/windows/lang_es.nsi diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsiBinary files differ index f038c0e419..7cd90ec314 100755 --- a/indra/newview/installers/windows/lang_fr.nsi +++ b/indra/newview/installers/windows/lang_fr.nsi diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsiBinary files differ index bd16d8318f..194062da9a 100755 --- a/indra/newview/installers/windows/lang_it.nsi +++ b/indra/newview/installers/windows/lang_it.nsi diff --git a/indra/newview/installers/windows/lang_ja.nsi b/indra/newview/installers/windows/lang_ja.nsiBinary files differ index 71edde1992..a54005ba14 100755 --- a/indra/newview/installers/windows/lang_ja.nsi +++ b/indra/newview/installers/windows/lang_ja.nsi diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsiBinary files differ index 865e8bdeee..355d806866 100644 --- a/indra/newview/installers/windows/lang_pl.nsi +++ b/indra/newview/installers/windows/lang_pl.nsi diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsiBinary files differ index 0e7cbeacda..97f5d2b44a 100755 --- a/indra/newview/installers/windows/lang_pt-br.nsi +++ b/indra/newview/installers/windows/lang_pt-br.nsi diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsiBinary files differ index d55aacc971..65a9f4846d 100755 --- a/indra/newview/installers/windows/lang_ru.nsi +++ b/indra/newview/installers/windows/lang_ru.nsi diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsiBinary files differ index 4746f84482..e71886cc66 100755 --- a/indra/newview/installers/windows/lang_tr.nsi +++ b/indra/newview/installers/windows/lang_tr.nsi diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsiBinary files differ index 397bd0ac81..f5f0c6cbdf 100755 --- a/indra/newview/installers/windows/lang_zh.nsi +++ b/indra/newview/installers/windows/lang_zh.nsi diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index b377d099be..d3a490f51f 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3911,16 +3911,6 @@ bool LLAgent::teleportCore(bool is_local)  	// hide the Region/Estate floater  	LLFloaterReg::hideInstance("region_info"); -	// minimize the Search floater (STORM-1474) -	{ -		LLFloater* instance = LLFloaterReg::getInstance("search"); - -		if (instance && instance->getVisible()) -		{ -			instance->setMinimized(TRUE); -		} -	} -  	LLViewerParcelMgr::getInstance()->deselectLand();  	LLViewerMediaFocus::getInstance()->clearFocus(); diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index ef56478106..debf93dccd 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -524,6 +524,11 @@ void LLAppCoreHttp::refreshSettings(bool initial)  LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,   	const LLCore::HttpHandler::ptr_t &handler, void *appdata)  { +    if (gDisconnected) +    { +        return LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT); +    } +      LLCore::HttpStatus result;      try      { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a2391ef889..73d0eac0ac 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1132,43 +1132,41 @@ bool LLAppViewer::init()  #if LL_RELEASE_FOR_DOWNLOAD      if (!gSavedSettings.getBOOL("CmdLineSkipUpdater"))      { -	LLProcess::Params updater; -	updater.desc = "updater process"; -	// Because it's the updater, it MUST persist beyond the lifespan of the -	// viewer itself. -	updater.autokill = false; -	std::string updater_file; +        LLProcess::Params updater; +        updater.desc = "updater process"; +        // Because it's the updater, it MUST persist beyond the lifespan of the +        // viewer itself. +        updater.autokill = false; +        std::string updater_file;  #if LL_WINDOWS -	updater_file = "SLVersionChecker.exe"; -	updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file); +        updater_file = "SLVersionChecker.exe"; +        updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);  #elif LL_DARWIN -	// explicitly run the system Python interpreter on SLVersionChecker.py -	updater.executable = "python"; -	updater_file = "SLVersionChecker.py"; -	updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", updater_file)); +        updater_file = "SLVersionChecker"; +        updater.executable = gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", updater_file);  #else -	updater_file = "SLVersionChecker"; -	updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file); +        updater_file = "SLVersionChecker"; +        updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);  #endif -	// add LEAP mode command-line argument to whichever of these we selected -	updater.args.add("leap"); -	// UpdaterServiceSettings -    if (gSavedSettings.getBOOL("FirstLoginThisInstall")) -    { -        // Befor first login, treat this as 'manual' updates, -        // updater won't install anything, but required updates -        updater.args.add("0"); -    } -    else -    { -        updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting"))); -    } -	// channel -	updater.args.add(LLVersionInfo::instance().getChannel()); -	// testok -	updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest"))); -	// ForceAddressSize -	updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize"))); +        // add LEAP mode command-line argument to whichever of these we selected +        updater.args.add("leap"); +        // UpdaterServiceSettings +        if (gSavedSettings.getBOOL("FirstLoginThisInstall")) +        { +            // Befor first login, treat this as 'manual' updates, +            // updater won't install anything, but required updates +            updater.args.add("0"); +        } +        else +        { +            updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting"))); +        } +        // channel +        updater.args.add(LLVersionInfo::instance().getChannel()); +        // testok +        updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest"))); +        // ForceAddressSize +        updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));          try          { @@ -1186,11 +1184,11 @@ bool LLAppViewer::init()                  OSMB_OK);              mUpdaterNotFound = true;          } -	} -	else -	{ -		LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL; -	} +    } +    else +    { +        LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL; +    }      if (mUpdaterNotFound)      { @@ -1223,12 +1221,12 @@ bool LLAppViewer::init()          }      } -	if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0) -	{ -		LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: " -							 << "lleventhost no longer supported as a dynamic library" -							 << LL_ENDL; -	} +    if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0) +    { +        LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: " +                             << "lleventhost no longer supported as a dynamic library" +                             << LL_ENDL; +    }  #endif //LL_RELEASE_FOR_DOWNLOAD  	LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; @@ -1743,12 +1741,14 @@ bool LLAppViewer::cleanup()  	// one because it happens just after mFastTimerLogThread is deleted. This  	// comment is in case we guessed wrong, so we can move it here instead. +#if LL_LINUX  	// remove any old breakpad minidump files from the log directory  	if (! isError())  	{  		std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");  		gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");  	} +#endif  	// Kill off LLLeap objects. We can find them all because LLLeap is derived  	// from LLInstanceTracker. @@ -1830,6 +1830,8 @@ bool LLAppViewer::cleanup()  	if (gAudiop)  	{ +        LL_INFOS() << "Shutting down audio" << LL_ENDL; +          // be sure to stop the internet stream cleanly BEFORE destroying the interface to stop it.          gAudiop->stopInternetStream();          // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem. @@ -4325,120 +4327,6 @@ void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)  void LLAppViewer::loadKeyBindings()  {  	std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); -#if 1 -	// Legacy support -	// Remove #if-#endif section half a year after DRTVWR-501 releases. -	// Mouse actions are part of keybinding file since DRTVWR-501 instead of being stored in -	// settings.xml. To support legacy viewers that were storing in  settings.xml we need to -	// transfer old variables to new format. -	// Also part of backward compatibility is present in LLKeyConflictHandler to modify -	// legacy variables on changes in new system (to make sure we won't enforce -	// legacy values again if user dropped to defaults in new system) -	if (LLVersionInfo::getInstance()->getChannelAndVersion() != gLastRunVersion -		|| !gDirUtilp->fileExists(key_bindings_file)) // if file is missing, assume that there were no changes by user yet -	{ -		// copy mouse actions and voice key changes to new file -		LL_INFOS("InitInfo") << "Converting legacy mouse bindings to new format" << LL_ENDL; -		// Load settings from file -		LLKeyConflictHandler third_person_view(LLKeyConflictHandler::MODE_THIRD_PERSON); -		LLKeyConflictHandler sitting_view(LLKeyConflictHandler::MODE_SITTING); - -		// Since we are only modifying keybindings if personal file doesn't exist yet, -		// it should be safe to just overwrite the value -		// If key is already in use somewhere by default, LLKeyConflictHandler should resolve it. -		BOOL value = gSavedSettings.getBOOL("DoubleClickAutoPilot"); -		third_person_view.registerControl("walk_to", -			0, -			value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE, -			KEY_NONE, -			MASK_NONE, -			value); - -		U32 index = value ? 1 : 0; // we can store multiple combinations per action, so if first is in use by doubleclick, go to second -		value = gSavedSettings.getBOOL("ClickToWalk"); -		third_person_view.registerControl("walk_to", -			index, -			value ? EMouseClickType::CLICK_LEFT : EMouseClickType::CLICK_NONE, -			KEY_NONE, -			MASK_NONE, -			value); - -		value = gSavedSettings.getBOOL("DoubleClickTeleport"); -		third_person_view.registerControl("teleport_to", -			0, -			value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE, -			KEY_NONE, -			MASK_NONE, -			value); - -		// sitting also supports teleport -		sitting_view.registerControl("teleport_to", -			0, -			value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE, -			KEY_NONE, -			MASK_NONE, -			value); - -		std::string key_string = gSavedSettings.getString("PushToTalkButton"); -		EMouseClickType mouse = EMouseClickType::CLICK_NONE; -		KEY key = KEY_NONE; -		if (key_string == "MiddleMouse") -		{ -			mouse = EMouseClickType::CLICK_MIDDLE; -		} -		else if (key_string == "MouseButton4") -		{ -			mouse = EMouseClickType::CLICK_BUTTON4; -		} -		else if (key_string == "MouseButton5") -		{ -			mouse = EMouseClickType::CLICK_BUTTON5; -		} -		else -		{ -			LLKeyboard::keyFromString(key_string, &key); -		} - -		value = gSavedSettings.getBOOL("PushToTalkToggle"); -		std::string control_name = value ? "toggle_voice" : "voice_follow_key"; -		third_person_view.registerControl(control_name, 0, mouse, key, MASK_NONE, true); -		sitting_view.registerControl(control_name, 0, mouse, key, MASK_NONE, true); - -		if (third_person_view.hasUnsavedChanges()) -		{ -			// calls loadBindingsXML() -			third_person_view.saveToSettings(); -		} - -		if (sitting_view.hasUnsavedChanges()) -		{ -			// calls loadBindingsXML() -			sitting_view.saveToSettings(); -		} - -		// in case of voice we need to repeat this in other modes - -		for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i) -		{ -			// edit and first person modes; MODE_SAVED_SETTINGS not in use at the moment -			if (i != LLKeyConflictHandler::MODE_THIRD_PERSON && i != LLKeyConflictHandler::MODE_SITTING) -			{ -				LLKeyConflictHandler handler((LLKeyConflictHandler::ESourceMode)i); - -				handler.registerControl(control_name, 0, mouse, key, MASK_NONE, true); - -				if (handler.hasUnsavedChanges()) -				{ -					// calls loadBindingsXML() -					handler.saveToSettings(); -				} -			} -		} -	} -	// since something might have gone wrong or there might have been nothing to save -	// (and because otherwise following code will have to be encased in else{}), -	// load everything one last time -#endif  	if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))  	{  		// Failed to load custom bindings, try default ones @@ -4768,6 +4656,10 @@ void LLAppViewer::idle()  	//  	// Special case idle if still starting up  	// +	if (LLStartUp::getStartupState() >= STATE_WORLD_INIT) +	{ +		update_texture_time(); +	}  	if (LLStartUp::getStartupState() < STATE_STARTED)  	{  		// Skip rest if idle startup returns false (essentially, no world yet) diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index 0fd6009074..d43048a8b6 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -99,22 +99,22 @@ void LLAttachmentsMgr::onIdle()  		return;  	} -    if (LLApp::isExiting()) -    { -        return; -    } +	if (LLApp::isExiting()) +	{ +		return; +	}  	requestPendingAttachments(); -    linkRecentlyArrivedAttachments(); +	linkRecentlyArrivedAttachments(); -    expireOldAttachmentRequests(); +	expireOldAttachmentRequests(); -    expireOldDetachRequests(); +	expireOldDetachRequests(); -    checkInvalidCOFLinks(); -     -    spamStatusInfo(); +	checkInvalidCOFLinks(); +	 +	spamStatusInfo();  }  void LLAttachmentsMgr::requestPendingAttachments() @@ -453,51 +453,55 @@ bool LLAttachmentsMgr::isAttachmentStateComplete() const  //  void LLAttachmentsMgr::checkInvalidCOFLinks()  { -        LLInventoryModel::cat_array_t cat_array; -        LLInventoryModel::item_array_t item_array; -        gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), -                                      cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); -        for (S32 i=0; i<item_array.size(); i++) -        { -            const LLViewerInventoryItem* inv_item = item_array.at(i).get(); -            const LLUUID& item_id = inv_item->getLinkedUUID(); -            if (inv_item->getType() == LLAssetType::AT_OBJECT) -            { -                LLTimer timer; -                bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer); -                bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id); -                if (is_wearing_attachment && is_flagged_questionable) -                { -                    LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now "  -                                        << (is_wearing_attachment ? "attached " : "")  -                                        <<"removing flag after " -                                        << timer.getElapsedTimeF32() << " item " -                                        << inv_item->getName() << " id " << item_id << LL_ENDL; -                    mQuestionableCOFLinks.removeTime(item_id); -                } -            } -        } +	if (!gInventory.isInventoryUsable()) +	{ +		return; +	} +	LLInventoryModel::cat_array_t cat_array; +	LLInventoryModel::item_array_t item_array; +	gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), +								  cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); +	for (S32 i=0; i<item_array.size(); i++) +	{ +		const LLViewerInventoryItem* inv_item = item_array.at(i).get(); +		const LLUUID& item_id = inv_item->getLinkedUUID(); +		if (inv_item->getType() == LLAssetType::AT_OBJECT) +		{ +			LLTimer timer; +			bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer); +			bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id); +			if (is_wearing_attachment && is_flagged_questionable) +			{ +				LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now "  +									<< (is_wearing_attachment ? "attached " : "")  +									<<"removing flag after " +									<< timer.getElapsedTimeF32() << " item " +									<< inv_item->getName() << " id " << item_id << LL_ENDL; +				mQuestionableCOFLinks.removeTime(item_id); +			} +		} +	} -        for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin(); -            it != mQuestionableCOFLinks.end(); ) -        { -            LLItemRequestTimes::iterator curr_it = it; -            ++it; -            const LLUUID& item_id = curr_it->first; -            LLViewerInventoryItem *inv_item = gInventory.getItem(item_id); -            if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME) -            { -                if (LLAppearanceMgr::instance().isLinkedInCOF(item_id)) -                { -                    LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after " -                                        << curr_it->second.getElapsedTimeF32() << " seconds for "  -                                        << (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; -                    LLAppearanceMgr::instance().removeCOFItemLinks(item_id); -                } -				mQuestionableCOFLinks.erase(curr_it); -                continue; -            } -        } +	for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin(); +		it != mQuestionableCOFLinks.end(); ) +	{ +		LLItemRequestTimes::iterator curr_it = it; +		++it; +		const LLUUID& item_id = curr_it->first; +		LLViewerInventoryItem *inv_item = gInventory.getItem(item_id); +		if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME) +		{ +			if (LLAppearanceMgr::instance().isLinkedInCOF(item_id)) +			{ +				LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after " +									<< curr_it->second.getElapsedTimeF32() << " seconds for "  +									<< (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; +				LLAppearanceMgr::instance().removeCOFItemLinks(item_id); +			} +			mQuestionableCOFLinks.erase(curr_it); +			continue; +		} +	}  }  void LLAttachmentsMgr::spamStatusInfo() diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 30ac35fff7..036215a845 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -40,7 +40,7 @@ LLBrowserNotification::LLBrowserNotification()  {  } -bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification) +bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification, bool should_log)  {  	LLUUID media_id = notification->getPayload()["media_id"].asUUID();  	auto media_instance = LLMediaCtrl::getInstance(media_id); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 9201c6bc00..aceedda07e 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -546,6 +546,7 @@ protected:  		static bool filterNotification(LLNotificationPtr notify);  		// connect counter updaters to the corresponding signals  		/*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } +		/*virtual*/ void onLoad(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); }  		/*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); }  		LLNotificationChiclet* const mChiclet; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 65cec68884..fee85d50bd 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -89,6 +89,7 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes  	mFlashStarted(false)  {  	mFlashTimer = new LLFlashTimer(); +	mAreChildrenInited = true; // inventory only  }  LLConversationViewSession::~LLConversationViewSession() diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index a163edf62c..4a0c9d399f 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -956,7 +956,7 @@ BOOL LLDrawable::updateGeometry(BOOL priority)  	LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE  	llassert(mVObjp.notNull()); -	BOOL res = mVObjp->updateGeometry(this); +	BOOL res = mVObjp && mVObjp->updateGeometry(this);  	return res;  } diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index e3c17f9877..f1a44a68c9 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -36,6 +36,7 @@  #include "llfloaterevent.h"  #include "llagent.h"  #include "llcommandhandler.h"	// secondlife:///app/... support +#include "lltrans.h"  class LLEventHandler : public LLCommandHandler  { @@ -218,8 +219,40 @@ void LLEventNotifier::load(const LLSD& event_options)  		end = event_options.endArray(); resp_it != end; ++resp_it)  	{  		LLSD response = *resp_it; - -		add(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString()); +        LLDate date; +        bool is_iso8601_date = false; + +        if (response["event_date"].isDate()) +        { +            date = response["event_date"].asDate(); +            is_iso8601_date = true; +        } +        else if (date.fromString(response["event_date"].asString())) +        { +            is_iso8601_date = true; +        } + +        if (is_iso8601_date) +        { +            std::string dateStr; + +            dateStr = "[" + LLTrans::getString("LTimeYear") + "]-[" +                + LLTrans::getString("LTimeMthNum") + "]-[" +                + LLTrans::getString("LTimeDay") + "] [" +                + LLTrans::getString("LTimeHour") + "]:[" +                + LLTrans::getString("LTimeMin") + "]:[" +                + LLTrans::getString("LTimeSec") + "]"; + +            LLSD substitution; +            substitution["datetime"] = date; +            LLStringUtil::format(dateStr, substitution); + +            add(response["event_id"].asInteger(), response["event_date_ut"], dateStr, response["event_name"].asString()); +        } +        else +        { +            add(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString()); +        }  	}  } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index b54c2105dd..b328dd2962 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1081,6 +1081,13 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to,  LLVector2* res_st_offs      F32 map_rot = 0.f, map_scaleS = 0.f, map_scaleT = 0.f, map_offsS = 0.f, map_offsT = 0.f; +    LLMaterial* mat = orig_tep->getMaterialParams(); +    if (!mat && map != LLRender::DIFFUSE_MAP) +    { +        LL_WARNS_ONCE("llface") << "Face is set to use specular or normal map but has no material, defaulting to diffuse" << LL_ENDL; +        map = LLRender::DIFFUSE_MAP; +    } +      switch (map)      {      case LLRender::DIFFUSE_MAP: @@ -1091,26 +1098,26 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to,  LLVector2* res_st_offs          map_offsT = orig_tep->mOffsetT;          break;      case LLRender::NORMAL_MAP: -        if (orig_tep->getMaterialParams()->getNormalID().isNull()) +        if (mat->getNormalID().isNull())          {              return false;          } -        map_rot = orig_tep->getMaterialParams()->getNormalRotation(); -        map_scaleS = orig_tep->getMaterialParams()->getNormalRepeatX(); -        map_scaleT = orig_tep->getMaterialParams()->getNormalRepeatY(); -        map_offsS = orig_tep->getMaterialParams()->getNormalOffsetX(); -        map_offsT = orig_tep->getMaterialParams()->getNormalOffsetY(); +        map_rot = mat->getNormalRotation(); +        map_scaleS = mat->getNormalRepeatX(); +        map_scaleT = mat->getNormalRepeatY(); +        map_offsS = mat->getNormalOffsetX(); +        map_offsT = mat->getNormalOffsetY();          break;      case LLRender::SPECULAR_MAP: -        if (orig_tep->getMaterialParams()->getSpecularID().isNull()) +        if (mat->getSpecularID().isNull())          {              return false;          } -        map_rot = orig_tep->getMaterialParams()->getSpecularRotation(); -        map_scaleS = orig_tep->getMaterialParams()->getSpecularRepeatX(); -        map_scaleT = orig_tep->getMaterialParams()->getSpecularRepeatY(); -        map_offsS = orig_tep->getMaterialParams()->getSpecularOffsetX(); -        map_offsT = orig_tep->getMaterialParams()->getSpecularOffsetY(); +        map_rot = mat->getSpecularRotation(); +        map_scaleS = mat->getSpecularRepeatX(); +        map_scaleT = mat->getSpecularRepeatY(); +        map_offsS = mat->getSpecularOffsetX(); +        map_offsT = mat->getSpecularOffsetY();          break;      default: /*make compiler happy*/          break; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index cca6b9ce32..c13b63433c 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1927,9 +1927,17 @@ BOOL LLFavoritesOrderStorage::saveFavoritesRecord(bool pref_changed)  	pref_changed |= mRecreateFavoriteStorage;  	mRecreateFavoriteStorage = false; +	// Can get called before inventory is done initializing. +	if (!gInventory.isInventoryUsable()) +	{ +		return FALSE; +	} +	  	LLUUID favorite_folder= gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);  	if (favorite_folder.isNull()) -			return FALSE; +	{ +		return FALSE; +	}  	LLInventoryModel::item_array_t items;  	LLInventoryModel::cat_array_t cats; diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 0b0567b687..4f3c2d8d34 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -730,11 +730,14 @@ void LLVolumeImplFlexible::preRebuild()  void LLVolumeImplFlexible::doFlexibleRebuild(bool rebuild_volume)  {  	LLVolume* volume = mVO->getVolume(); -	if(rebuild_volume) -	{ -		volume->setDirty(); -	} -	volume->regen(); +    if (volume) +    { +        if (rebuild_volume) +        { +            volume->setDirty(); +        } +        volume->regen(); +    }  	mUpdated = TRUE;  } diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index 745f154535..ffbb0bbee9 100644 --- a/indra/newview/llfloater360capture.cpp +++ b/indra/newview/llfloater360capture.cpp @@ -102,6 +102,7 @@ BOOL LLFloater360Capture::postBuild()      mWebBrowser = getChild<LLMediaCtrl>("360capture_contents");      mWebBrowser->addObserver(this); +    mWebBrowser->setAllowFileDownload(true);      // There is a group of radio buttons that define the quality      // by each having a 'value' that is returns equal to the pixel diff --git a/indra/newview/llfloatereditenvironmentbase.h b/indra/newview/llfloatereditenvironmentbase.h index 7c7cf5bdcd..d900d7f003 100644 --- a/indra/newview/llfloatereditenvironmentbase.h +++ b/indra/newview/llfloatereditenvironmentbase.h @@ -107,7 +107,7 @@ protected:      void                    onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status); -private: +protected:      LLUUID                  mExpectingAssetId; // for asset load confirmation  }; diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index 281d4f68f5..24673d5a7c 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -98,6 +98,11 @@ namespace {      const std::string TABS_SKYS("sky_tabs");      const std::string TABS_WATER("water_tabs"); +    // 'Play' buttons +    const std::string BTN_PLAY("play_btn"); +    const std::string BTN_SKIP_BACK("skip_back_btn"); +    const std::string BTN_SKIP_FORWARD("skip_forward_btn"); +      const std::string EVNT_DAYTRACK("DayCycle.Track");      const std::string EVNT_PLAY("DayCycle.PlayActions"); @@ -1205,6 +1210,11 @@ void LLFloaterEditExtDayCycle::updateButtons()      mDeleteFrameButton->setEnabled(can_manipulate && isRemovingFrameAllowed());      mLoadFrame->setEnabled(can_manipulate); +    BOOL enable_play = mEditDay ? TRUE : FALSE; +    childSetEnabled(BTN_PLAY, enable_play); +    childSetEnabled(BTN_SKIP_BACK, enable_play); +    childSetEnabled(BTN_SKIP_FORWARD, enable_play); +      // update track buttons      bool extended_env = LLEnvironment::instance().isExtendedEnvironmentEnabled();      for (S32 track = 0; track < LLSettingsDay::TRACK_MAX; ++track) @@ -1575,15 +1585,23 @@ void LLFloaterEditExtDayCycle::onIdlePlay(void* user_data)      {          LLFloaterEditExtDayCycle* self = (LLFloaterEditExtDayCycle*)user_data; -        F32 prcnt_played = self->mPlayTimer.getElapsedTimeF32() / DAY_CYCLE_PLAY_TIME_SECONDS; -        F32 new_frame = fmod(self->mPlayStartFrame + prcnt_played, 1.f); +        if (self->mSkyBlender == nullptr || self->mWaterBlender == nullptr) +        { +            self->stopPlay(); +        } +        else +        { + +            F32 prcnt_played = self->mPlayTimer.getElapsedTimeF32() / DAY_CYCLE_PLAY_TIME_SECONDS; +            F32 new_frame = fmod(self->mPlayStartFrame + prcnt_played, 1.f); -        self->mTimeSlider->setCurSliderValue(new_frame); // will do the rounding -        self->mSkyBlender->setPosition(new_frame); -        self->mWaterBlender->setPosition(new_frame); -        self->synchronizeTabs(); -        self->updateTimeAndLabel(); -        self->updateButtons(); +            self->mTimeSlider->setCurSliderValue(new_frame); // will do the rounding +            self->mSkyBlender->setPosition(new_frame); +            self->mWaterBlender->setPosition(new_frame); +            self->synchronizeTabs(); +            self->updateTimeAndLabel(); +            self->updateButtons(); +        }      }  } diff --git a/indra/newview/llfloatereditextdaycycle.h b/indra/newview/llfloatereditextdaycycle.h index 9a30fb199f..ab5d12fa36 100644 --- a/indra/newview/llfloatereditextdaycycle.h +++ b/indra/newview/llfloatereditextdaycycle.h @@ -194,8 +194,6 @@ private:      std::string                 mLastFrameSlider;      bool                        mShiftCopyEnabled; -    LLUUID                      mExpectingAssetId; -      LLButton*                   mAddFrameButton;      LLButton*                   mDeleteFrameButton;      LLButton*                   mImportButton; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 112ece0fbf..1525bb9952 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1690,7 +1690,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool      /* floater processing */ -	if (NULL != session_floater) +	if (NULL != session_floater && !session_floater->isDead())  	{  		if (session_id != getSelectedSession())  		{ @@ -1862,11 +1862,14 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c  	if (widget)  	{  		is_widget_selected = widget->isSelected(); -		new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); -		if (!new_selection) -		{ -			new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); -		} +        if (mConversationsRoot) +        { +            new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); +            if (!new_selection) +            { +                new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); +            } +        }  		// Will destroy views and delete models that are not assigned to any views  		widget->destroyView(); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 441979389e..43dc304c10 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -384,13 +384,16 @@ void LLFloaterIMSessionTab::draw()  void LLFloaterIMSessionTab::enableDisableCallBtn()  { -    mVoiceButton->setEnabled( -    		mSessionID.notNull() -    		&& mSession -    		&& mSession->mSessionInitialized -    		&& LLVoiceClient::getInstance()->voiceEnabled() -    		&& LLVoiceClient::getInstance()->isVoiceWorking() -    		&& mSession->mCallBackEnabled); +    if (LLVoiceClient::instanceExists()) +    { +        mVoiceButton->setEnabled( +            mSessionID.notNull() +            && mSession +            && mSession->mSessionInitialized +            && LLVoiceClient::getInstance()->voiceEnabled() +            && LLVoiceClient::getInstance()->isVoiceWorking() +            && mSession->mCallBackEnabled); +    }  }  void LLFloaterIMSessionTab::onFocusReceived() diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index af0e56e448..04133f2710 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2468,6 +2468,7 @@ BOOL LLPanelLandAccess::postBuild()  	{  		mListBanned->sortByColumnIndex(0, TRUE); // ascending  		mListBanned->setContextMenu(LLScrollListCtrl::MENU_AVATAR); +		mListBanned->setAlternateSort();  	}  	return TRUE; @@ -2570,11 +2571,12 @@ void LLPanelLandAccess::refresh()  			{  				const LLAccessEntry& entry = (*cit).second;  				std::string duration; +				S32 seconds = -1;  				if (entry.mTime != 0)  				{  					LLStringUtil::format_map_t args;  					S32 now = time(NULL); -					S32 seconds = entry.mTime - now;					 +					seconds = entry.mTime - now;					  					if (seconds < 0) seconds = 0;  					if (seconds >= 7200) @@ -2611,6 +2613,7 @@ void LLPanelLandAccess::refresh()  				columns[0]["column"] = "name"; // to be populated later  				columns[1]["column"] = "duration";  				columns[1]["value"] = duration; +				columns[1]["alt_value"] = entry.mTime != 0 ? std::to_string(seconds) : "Always";  				mListBanned->addElement(item);  			}  			mListBanned->sortByName(TRUE); diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp index 749a3d2686..8633fe4e5e 100644 --- a/indra/newview/llfloaterlandholdings.cpp +++ b/indra/newview/llfloaterlandholdings.cpp @@ -108,6 +108,9 @@ LLFloaterLandHoldings::~LLFloaterLandHoldings()  void LLFloaterLandHoldings::onOpen(const LLSD& key)  { +    LLScrollListCtrl *list = getChild<LLScrollListCtrl>("parcel list"); +    list->clearRows(); +  	// query_id null is known to be us  	const LLUUID& query_id = LLUUID::null; diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index c907dfc969..6135c4f13e 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -40,6 +40,7 @@  #include "llagent.h"  #include "llbutton.h"  #include "llcombobox.h" +#include "llfloaterreg.h"  #include "llfocusmgr.h"  #include "llmeshrepository.h"  #include "llnotificationsutil.h" @@ -343,10 +344,30 @@ void LLFloaterModelPreview::initModelPreview()  	mModelPreview = new LLModelPreview(tex_width, tex_height, this);      mModelPreview->setPreviewTarget(PREVIEW_CAMERA_DISTANCE); -	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5)); +	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3));  	mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::modelUpdated, this, _1));  } +//static +bool LLFloaterModelPreview::showModelPreview() +{ +#ifdef LL_GLOD +    if (LLRender::sGLCoreProfile) +    { +        // GLOD is incompatible with RenderGLCoreProfile, will crash on init +        LLNotificationsUtil::add("MeshUploadProfilerError"); +        return false; +    } +#endif + +    LLFloaterModelPreview* fmp = (LLFloaterModelPreview*)LLFloaterReg::getInstance("upload_model"); +    if (fmp && !fmp->isModelLoading()) +    { +        fmp->loadHighLodModel(); +    } +    return true; +} +  void LLFloaterModelPreview::onUploadOptionChecked(LLUICtrl* ctrl)  {  	if (mModelPreview) @@ -816,9 +837,6 @@ void LLFloaterModelPreview::draw()  		}  	} -	childSetTextArg("prim_cost", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost)); -	childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size())); -      if (!isMinimized() && mModelPreview->lodsReady())  	{  		draw3dPreview(); @@ -1558,7 +1576,7 @@ void LLFloaterModelPreview::addStringToLogTab(const std::string& str, bool flash  	}  	} -void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost) +void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z)  {  	assert_main_thread();  	childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x)); @@ -1731,7 +1749,6 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)  void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)  {  	mModelPreview->updateLodControls(lod); -	refresh();  	LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);      S32 index = lod_source_combo->getCurrentIndex(); diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 51f9b3a0e2..1e147cd555 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -73,6 +73,7 @@ public:      /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);  	void initModelPreview(); +	static bool showModelPreview();  	BOOL handleMouseDown(S32 x, S32 y, MASK mask);  	BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -90,7 +91,7 @@ public:  	void clearAvatarTab(); // clears table  	void updateAvatarTab(bool highlight_overrides); // populates table and data as nessesary -	void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost); +	void setDetails(F32 x, F32 y, F32 z);  	void setPreviewLOD(S32 lod);  	void onBrowseLOD(S32 lod); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 41ae39152b..a57705fe50 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2602,6 +2602,9 @@ void LLPanelPreferenceControls::populateControlTable()          LL_WARNS() << "Unimplemented mode" << LL_ENDL;      } +    // explicit update to make sure table is ready for llsearchableui +    pControlsTable->updateColumns(); +      // Searchable columns were removed and readded, mark searchables for an update      // Note: at the moment tables/lists lack proper llsearchableui support      LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp index 9a23d99802..cda4dc8bcc 100644 --- a/indra/newview/llfloatertexturefetchdebugger.cpp +++ b/indra/newview/llfloatertexturefetchdebugger.cpp @@ -38,6 +38,7 @@  #include "llappviewer.h"  #include "lltexturefetch.h"  #include "llviewercontrol.h" +#include "llviewerassetstats.h" //gTextureTimer  LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)  	: LLFloater(key), @@ -50,6 +51,7 @@ LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)  	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.ResetFetchTime",	boost::bind(&LLFloaterTextureFetchDebugger::onClickResetFetchTime, this));  	mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead",	boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this));  	mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite",	boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this)); @@ -228,6 +230,12 @@ void LLFloaterTextureFetchDebugger::onClickClose()  	delete this;  } +void LLFloaterTextureFetchDebugger::onClickResetFetchTime() +{ +	gTextureTimer.start(); +	gTextureTimer.pause(); +} +  void LLFloaterTextureFetchDebugger::onClickClear()  {  	mButtonStateMap["start_btn"] = true; diff --git a/indra/newview/llfloatertexturefetchdebugger.h b/indra/newview/llfloatertexturefetchdebugger.h index 096ad88e07..637f3b03e5 100644 --- a/indra/newview/llfloatertexturefetchdebugger.h +++ b/indra/newview/llfloatertexturefetchdebugger.h @@ -44,6 +44,7 @@ public:  	void onClickStart();  	void onClickClear();  	void onClickClose(); +	void onClickResetFetchTime();  	void onClickCacheRead();  	void onClickCacheWrite(); diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 63bce3d2eb..d5c2ad5f81 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -204,6 +204,7 @@ void LLFloaterURLEntry::onBtnOK( void* userdata )  	self->getChildView("ok_btn")->setEnabled(false);  	self->getChildView("cancel_btn")->setEnabled(false);  	self->getChildView("media_entry")->setEnabled(false); +    self->getChildView("clear_btn")->setEnabled(false);  }  // static diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index d40a7234e2..b6d856e31b 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -66,7 +66,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )  {  	LL_RECORD_BLOCK_TIME(FTM_INVENTORY_SORT); -	if (!needsSort(folder->getViewModelItem())) return; +	if (!folder->areChildrenInited() || !needsSort(folder->getViewModelItem())) return;  	LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem());  	if (modelp->getUUID().isNull()) return; @@ -132,6 +132,16 @@ bool LLFolderViewModelInventory::isFolderComplete(LLFolderViewFolder* folder)  	return false;  } +//virtual +void LLFolderViewModelItemInventory::addChild(LLFolderViewModelItem* child) +{ +    LLFolderViewModelItemInventory* model_child = static_cast<LLFolderViewModelItemInventory*>(child); +    mLastAddedChildCreationDate = model_child->getCreationDate(); + +    // this will requestSort() +    LLFolderViewModelItemCommon::addChild(child); +} +  void LLFolderViewModelItemInventory::requestSort()  {  	LLFolderViewModelItemCommon::requestSort(); @@ -140,15 +150,31 @@ void LLFolderViewModelItemInventory::requestSort()  	{  		folderp->requestArrange();  	} -	if (static_cast<LLFolderViewModelInventory&>(mRootViewModel).getSorter().isByDate()) -	{ -		// sort by date potentially affects parent folders which use a date -		// derived from newest item in them -		if (mParent) -		{ -			mParent->requestSort(); -		} -	} +    LLInventorySort sorter = static_cast<LLFolderViewModelInventory&>(mRootViewModel).getSorter(); + +    // Sort by date potentially affects parent folders which use a date +    // derived from newest item in them +    if (sorter.isByDate() && mParent) +    { +        // If this is an item, parent needs to be resorted +        // This case shouldn't happen, unless someone calls item->requestSort() +        if (!folderp) +        { +            mParent->requestSort(); +        } +        // if this is a folder, check sort rules for folder first +        else if (sorter.isFoldersByDate()) +        { +            if (mLastAddedChildCreationDate == -1  // nothing was added, some other reason for resort +                || mLastAddedChildCreationDate > getCreationDate()) // newer child +            { +                LLFolderViewModelItemInventory* model_parent = static_cast<LLFolderViewModelItemInventory*>(mParent); +                model_parent->mLastAddedChildCreationDate = mLastAddedChildCreationDate; +                mParent->requestSort(); +            } +        } +    } +    mLastAddedChildCreationDate = -1;  }  void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size) @@ -387,6 +413,7 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a,  LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model ) :      LLFolderViewModelItemCommon(root_view_model), -    mPrevPassedAllFilters(false) +    mPrevPassedAllFilters(false), +    mLastAddedChildCreationDate(-1)  {  } diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 51b98339c4..de28091c32 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -47,6 +47,7 @@ public:  	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make   into pure virtual.  	virtual BOOL isAgentInventory() const { return FALSE; }  	virtual BOOL isUpToDate() const = 0; +    virtual void addChild(LLFolderViewModelItem* child);  	virtual bool hasChildren() const = 0;  	virtual LLInventoryType::EType getInventoryType() const = 0;  	virtual void performAction(LLInventoryModel* model, std::string action)   = 0; @@ -63,6 +64,7 @@ public:  	virtual LLToolDragAndDrop::ESource getDragSource() const = 0;  protected:      bool mPrevPassedAllFilters; +    time_t mLastAddedChildCreationDate; // -1 if nothing was added  };  class LLInventorySort @@ -83,6 +85,8 @@ public:  	}  	bool isByDate() const { return mByDate; } +	bool isFoldersByName() const { return (!mByDate || mFoldersByName) && !mFoldersByWeight; } +    bool isFoldersByDate() const { return mByDate && !mFoldersByName && !mFoldersByWeight; }  	U32 getSortOrder() const { return mSortOrder; }  	void toParams(Params& p) { p.order(mSortOrder);}  	void fromParams(Params& p)  diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 12d82d101f..9dca509262 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -372,6 +372,11 @@ void LLGroupActions::show(const LLUUID& group_id)  	params["open_tab_name"] = "panel_group_info_sidetray";  	LLFloaterSidePanelContainer::showPanel("people", "panel_group_info_sidetray", params); +    LLFloater *floater = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>("people"); +    if (!floater->isFrontmost()) +    { +        floater->setVisibleAndFrontmost(TRUE, params); +    }  }  void LLGroupActions::refresh_notices() diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 9d8bf7f51c..7be35ac260 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -330,7 +330,7 @@ void LLHUDText::updateVisibility()  	if (!mSourceObject)  	{ -		//LL_WARNS() << "LLHUDText::updateScreenPos -- mSourceObject is NULL!" << LL_ENDL; +		LL_WARNS() << "HUD text: mSourceObject is NULL,  mOnHUDAttachment: " << mOnHUDAttachment << LL_ENDL;  		mVisible = TRUE;  		if (mOnHUDAttachment)  		{ diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index c2b29f36e8..0fa3dc1110 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -60,7 +60,7 @@ void LLIMHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLIMHandler::processNotification(const LLNotificationPtr& notification) +bool LLIMHandler::processNotification(const LLNotificationPtr& notification, bool should_log)  {      if(notification->isDND())      { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index f5358ba5f2..b7e0a6a794 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -900,7 +900,7 @@ bool LLIMModel::LLIMSession::isOutgoingAdHoc() const  bool LLIMModel::LLIMSession::isAdHoc()  { -	return IM_SESSION_CONFERENCE_START == mType || (IM_SESSION_INVITE == mType && !gAgent.isInGroup(mSessionID)); +	return IM_SESSION_CONFERENCE_START == mType || (IM_SESSION_INVITE == mType && !gAgent.isInGroup(mSessionID, TRUE));  }  bool LLIMModel::LLIMSession::isP2P() @@ -910,7 +910,7 @@ bool LLIMModel::LLIMSession::isP2P()  bool LLIMModel::LLIMSession::isGroupChat()  { -	return IM_SESSION_GROUP_START == mType || (IM_SESSION_INVITE == mType && gAgent.isInGroup(mSessionID)); +	return IM_SESSION_GROUP_START == mType || (IM_SESSION_INVITE == mType && gAgent.isInGroup(mSessionID, TRUE));  }  bool LLIMModel::LLIMSession::isOtherParticipantAvaline() @@ -1700,7 +1700,7 @@ LLUUID LLIMMgr::computeSessionID(  		}  	} -	if (gAgent.isInGroup(session_id) && (session_id != other_participant_id)) +	if (gAgent.isInGroup(session_id, TRUE) && (session_id != other_participant_id))  	{  		LL_WARNS() << "Group session id different from group id: IM type = " << dialog << ", session id = " << session_id << ", group id = " << other_participant_id << LL_ENDL;  	} @@ -2034,7 +2034,7 @@ void LLCallDialog::setIcon(const LLSD& session_id, const LLSD& participant_id)  	// *NOTE: 12/28/2009: check avaline calls: LLVoiceClient::isParticipantAvatar returns false for them  	bool participant_is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); -	bool is_group = participant_is_avatar && gAgent.isInGroup(session_id); +	bool is_group = participant_is_avatar && gAgent.isInGroup(session_id, TRUE);  	LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon");  	LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon"); @@ -2329,7 +2329,7 @@ BOOL LLIncomingCallDialog::postBuild()  	}  	std::string call_type; -	if (gAgent.isInGroup(session_id)) +	if (gAgent.isInGroup(session_id, TRUE))  	{  		LLStringUtil::format_map_t args;  		LLGroupData data; @@ -2506,8 +2506,8 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload  				switch(type){  				case IM_SESSION_CONFERENCE_START:  				case IM_SESSION_GROUP_START: -				case IM_SESSION_INVITE:		 -					if (gAgent.isInGroup(session_id)) +				case IM_SESSION_INVITE: +					if (gAgent.isInGroup(session_id, TRUE))  					{  						LLGroupData data;  						if (!gAgent.getGroupData(session_id, data)) break; @@ -3054,7 +3054,7 @@ void LLIMMgr::inviteToSession(  		notify_box_type = "VoiceInviteP2P";  		voice_invite = TRUE;  	} -	else if ( gAgent.isInGroup(session_id) ) +	else if ( gAgent.isInGroup(session_id, TRUE) )  	{  		//only really old school groups have voice invitations  		notify_box_type = "VoiceInviteGroup"; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3609c5e457..06c8f66c1e 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1888,7 +1888,8 @@ void LLItemBridge::buildDisplayName() const  	LLStringUtil::toUpper(mSearchableName);  	//Name set, so trigger a sort -	if(mParent) +    LLInventorySort sorter = static_cast<LLFolderViewModelInventory&>(mRootViewModel).getSorter(); +	if(mParent && !sorter.isByDate())  	{  		mParent->requestSort();  	} @@ -2187,7 +2188,8 @@ void LLFolderBridge::buildDisplayName() const  	LLStringUtil::toUpper(mSearchableName);      //Name set, so trigger a sort -    if(mParent) +    LLInventorySort sorter = static_cast<LLFolderViewModelInventory&>(mRootViewModel).getSorter(); +    if(mParent && sorter.isFoldersByName())      {          mParent->requestSort();      } @@ -3420,9 +3422,22 @@ void LLFolderBridge::copyOutfitToClipboard()  void LLFolderBridge::openItem()  {  	LL_DEBUGS() << "LLFolderBridge::openItem()" << LL_ENDL; -	LLInventoryModel* model = getInventoryModel(); -	if(!model) return; -	if(mUUID.isNull()) return; + +    LLInventoryPanel* panel = mInventoryPanel.get(); +    if (!panel) +    { +        return; +    } +    LLInventoryModel* model = getInventoryModel(); +    if (!model) +    { +        return; +    } +    if (mUUID.isNull()) +    { +        return; +    } +    panel->onFolderOpening(mUUID);  	bool fetching_inventory = model->fetchDescendentsOf(mUUID);  	// Only change folder type if we have the folder contents.  	if (!fetching_inventory) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 9cc67766ca..d239b23e83 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -255,7 +255,7 @@ void update_marketplace_folder_hierarchy(const LLUUID cat_id)      return;  } -void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistency_enforcement) +void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistency_enforcement, bool skip_clear_listing)  {      // When changing the marketplace status of an item, we usually have to change the status of all      // folders in the same listing. This is because the display of each folder is affected by the @@ -327,7 +327,7 @@ void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistenc      else      {          // If the folder is outside the marketplace listings root, clear its SLM data if needs be -        if (perform_consistency_enforcement && LLMarketplaceData::instance().isListed(cur_uuid)) +        if (perform_consistency_enforcement && !skip_clear_listing && LLMarketplaceData::instance().isListed(cur_uuid))          {              LL_INFOS("SLM") << "Disassociate as the listing folder is not under the marketplace folder anymore!!" << LL_ENDL;              LLMarketplaceData::instance().clearListing(cur_uuid); @@ -1843,7 +1843,7 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_  		result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1);  	} -    update_marketplace_category(cat->getUUID()); +    update_marketplace_category(cat->getUUID(), true, true);      gInventory.notifyObservers();      return result && !has_bad_items;  } diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 2cb2b1e877..8915bfa1e0 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -68,7 +68,7 @@ void show_item_original(const LLUUID& item_uuid);  void reset_inventory_filter();  // Nudge the listing categories in the inventory to signal that their marketplace status changed -void update_marketplace_category(const LLUUID& cat_id, bool perform_consistency_enforcement = true); +void update_marketplace_category(const LLUUID& cat_id, bool perform_consistency_enforcement = true, bool skip_clear_listing = false);  // Nudge all listing categories to signal that their marketplace status changed  void update_all_marketplace_count(); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ba453471c6..b4fc832596 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -27,6 +27,7 @@  #include "llviewerprecompiledheaders.h"  #include <typeinfo> +#include <random>  #include "llinventorymodel.h" @@ -67,6 +68,9 @@  #include "process.h"  #endif +#include <algorithm> +#include <boost/algorithm/string/join.hpp> +  // Increment this if the inventory contents change in a non-backwards-compatible way.  // For viewer 2, the addition of link items makes a pre-viewer-2 cache incorrect.  const S32 LLInventoryModel::sCurrentInvCacheVersion = 2; @@ -129,6 +133,60 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)  }  ///---------------------------------------------------------------------------- +/// Class LLInventoryValidationInfo +///---------------------------------------------------------------------------- +LLInventoryValidationInfo::LLInventoryValidationInfo(): +	mFatalErrorCount(0), +	mWarningCount(0), +	mInitialized(false), +	mFatalNoRootFolder(false), +	mFatalNoLibraryRootFolder(false), +	mFatalQADebugMode(false) +{ +} + +void LLInventoryValidationInfo::toOstream(std::ostream& os) const +{ +	os << "mFatalErrorCount " << mFatalErrorCount << " mWarningCount " << mWarningCount; +} + + +std::ostream& operator<<(std::ostream& os, const LLInventoryValidationInfo& v) +{ +	v.toOstream(os); +	return os; +} + +void LLInventoryValidationInfo::asLLSD(LLSD& sd) const +{ +	sd["fatal_error_count"] = mFatalErrorCount; +	sd["warning_count"] = mWarningCount; +	sd["initialized"] = mInitialized; +	sd["missing_system_folders_count"] = LLSD::Integer(mMissingRequiredSystemFolders.size()); +	sd["fatal_no_root_folder"] = mFatalNoRootFolder; +	sd["fatal_no_library_root_folder"] = mFatalNoLibraryRootFolder; +	sd["fatal_qa_debug_mode"] = mFatalQADebugMode; +	if (mMissingRequiredSystemFolders.size()>0) +	{ +		sd["missing_system_folders"] = LLSD::emptyArray(); +		for(auto ft: mMissingRequiredSystemFolders) +		{ +			sd["missing_system_folders"].append(LLFolderType::lookup(ft));  +		} +	} +	sd["duplicate_system_folders_count"] = LLSD::Integer(mDuplicateRequiredSystemFolders.size()); +	if (mDuplicateRequiredSystemFolders.size()>0) +	{ +		sd["duplicate_system_folders"] = LLSD::emptyArray(); +		for(auto ft: mDuplicateRequiredSystemFolders) +		{ +			sd["duplicate_system_folders"].append(LLFolderType::lookup(ft)); +		} +	} +	 +} + +///----------------------------------------------------------------------------  /// Class LLInventoryModel  ///---------------------------------------------------------------------------- @@ -160,7 +218,8 @@ LLInventoryModel::LLInventoryModel()  	mHttpPriorityFG(0),  	mHttpPriorityBG(0),  	mCategoryLock(), -	mItemLock() +	mItemLock(), +	mValidationInfo(new LLInventoryValidationInfo)  {} @@ -500,12 +559,18 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(  		}  	} -	if(rv.isNull() && isInventoryUsable() && create_folder) +	if(rv.isNull() && create_folder && root_id.notNull())  	{ -		if(root_id.notNull()) + +		if (isInventoryUsable())  		{  			return createNewCategory(root_id, preferred_type, LLStringUtil::null);  		} +		else +		{ +			LL_WARNS("Inventory") << "Can't create requested folder, type " << preferred_type +								  << " because inventory is not usable" << LL_ENDL; +		}  	}  	return rv;  } @@ -569,20 +634,30 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,  										   const std::string& pname,  										   inventory_func_type callback)  { -	  	LLUUID id; -	if(!isInventoryUsable()) +	if (!isInventoryUsable())  	{ -		LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL; +		LL_WARNS(LOG_INV) << "Inventory is not usable; can't create requested category of type " +						  << preferred_type << LL_ENDL; +		// FIXME failing but still returning an id?  		return id;  	}  	if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup())  	{  		LL_DEBUGS(LOG_INV) << "Attempt to create undefined category." << LL_ENDL; +		// FIXME failing but still returning an id?  		return id;  	} +	if (preferred_type != LLFolderType::FT_NONE) +	{ +		// Ultimately this should only be done for non-singleton +		// types. Requires back-end changes to guarantee that others +		// already exist. +		LL_WARNS(LOG_INV) << "Creating new system folder, type " << preferred_type << LL_ENDL; +	} +  	id.generate();  	std::string name = pname;  	if(!pname.empty()) @@ -612,7 +687,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,  		request["message"] = "CreateInventoryCategory";  		request["payload"] = body; -		LL_DEBUGS(LOG_INV) << "create category request: " << ll_pretty_print_sd(request) << LL_ENDL; +		LL_DEBUGS(LOG_INV) << "Creating category via request: " << ll_pretty_print_sd(request) << LL_ENDL;          LLCoros::instance().launch("LLInventoryModel::createNewCategoryCoro",              boost::bind(&LLInventoryModel::createNewCategoryCoro, this, url, body, callback)); @@ -624,6 +699,10 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,  		return LLUUID::null;  	} +	// FIXME this UDP code path needs to be removed. Requires +	// reworking many of the callers to use callbacks rather than +	// assuming instant success. +  	// Add the category to the internal representation  	LLPointer<LLViewerInventoryCategory> cat =  		new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID()); @@ -633,6 +712,8 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,  	accountForUpdate(update);  	updateCategory(cat); +	LL_DEBUGS(LOG_INV) << "Creating category via UDP message CreateInventoryFolder, type " << preferred_type << LL_ENDL; +  	// Create the category on the server. We do this to prevent people  	// from munging their protected folders.  	LLMessageSystem* msg = gMessageSystem; @@ -1711,7 +1792,20 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)          mModifyMask |= mask;      } -	if (referent.notNull() && (mChangedItemIDs.find(referent) == mChangedItemIDs.end())) +    bool needs_update = false; +    if (referent.notNull()) +    { +        if (mIsNotifyObservers) +        { +            needs_update = mChangedItemIDsBacklog.find(referent) == mChangedItemIDsBacklog.end(); +        } +        else +        { +            needs_update = mChangedItemIDs.find(referent) == mChangedItemIDs.end(); +        } +    } + +    if (needs_update)  	{          if (mIsNotifyObservers)          { @@ -1722,6 +1816,8 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)              mChangedItemIDs.insert(referent);          } +        // Fix me: From DD-81, probably shouldn't be here, instead +        // should be somewhere in an observer          update_marketplace_category(referent, false);          if (mask & LLInventoryObserver::ADD) @@ -2282,11 +2378,11 @@ bool LLInventoryModel::loadSkeleton(  					}  				} - 				LL_INFOS(LOG_INV) << "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." << LL_ENDL; + 				LL_DEBUGS(LOG_INV) << "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." << LL_ENDL;  			}  		} @@ -2312,7 +2408,10 @@ bool LLInventoryModel::loadSkeleton(  			cat->setVersion(NO_VERSION);  			LL_DEBUGS(LOG_INV) << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << LL_ENDL;  		} -		LL_INFOS(LOG_INV) << "Invalidated " << invalid_categories.size() << " categories due to invalid descendents cache" << LL_ENDL; +		if (invalid_categories.size() > 0) +		{ +			LL_DEBUGS(LOG_INV) << "Invalidated " << invalid_categories.size() << " categories due to invalid descendents cache" << LL_ENDL; +		}  		// At this point, we need to set the known descendents for each  		// category which successfully cached so that we do not @@ -2600,10 +2699,22 @@ void LLInventoryModel::buildParentChildMap()  				}  			} -			// 'My Inventory', -			// root of the agent's inv found. -			// The inv tree is built. -			mIsAgentInvUsable = true; +			LLPointer<LLInventoryValidationInfo> validation_info = validate(); +			if (validation_info->mFatalErrorCount > 0) +			{ +				// Fatal inventory error. Will not be able to engage in many inventory operations. +				// This should be followed by an error dialog leading to logout. +				LL_WARNS("Inventory") << "Fatal errors were found in validate(): unable to initialize inventory! " +									  << "Will not be able to do normal inventory operations in this session." +									  << LL_ENDL; +				mIsAgentInvUsable = false; +			} +			else +			{ +				mIsAgentInvUsable = true; +			} +			validation_info->mInitialized = true; +			mValidationInfo = validation_info;  			// notifyObservers() has been moved to  			// llstartup/idle_startup() after this func completes. @@ -2611,11 +2722,6 @@ void LLInventoryModel::buildParentChildMap()  			// observers start firing.  		}  	} - -	if (!gInventory.validate()) -	{ -	 	LL_WARNS(LOG_INV) << "model failed validity check!" << LL_ENDL; -	}  }  // Would normally do this at construction but that's too early @@ -3740,66 +3846,70 @@ void LLInventoryModel::dumpInventory() const  }  // Do various integrity checks on model, logging issues found and -// returning an overall good/bad flag. -bool LLInventoryModel::validate() const +// returning an overall good/bad flag.  +LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const  { -    const S32 MAX_VERBOSE_ERRORS = 40; // too many errors can cause disconect or freeze -    S32 error_count = 0; +	LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo; +	S32 fatalities = 0; +	S32 warnings = 0;  	if (getRootFolderID().isNull())  	{ -		LL_WARNS() << "no root folder id" << LL_ENDL; -        error_count++; +		LL_WARNS("Inventory") << "Fatal inventory corruption: no root folder id" << LL_ENDL; +		validation_info->mFatalNoRootFolder = true; +		fatalities++;  	}  	if (getLibraryRootFolderID().isNull())  	{ -		LL_WARNS() << "no root folder id" << LL_ENDL; -        error_count++; +		LL_WARNS("Inventory") << "Fatal inventory corruption: no library root folder id" << LL_ENDL; +		validation_info->mFatalNoLibraryRootFolder = true; +		fatalities++;  	}  	if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())  	{  		// ParentChild should be one larger because of the special entry for null uuid. -		LL_INFOS() << "unexpected sizes: cat map size " << mCategoryMap.size() -				<< " parent/child " << mParentChildCategoryTree.size() << LL_ENDL; -        error_count++; +		LL_INFOS("Inventory") << "unexpected sizes: cat map size " << mCategoryMap.size() +							  << " parent/child " << mParentChildCategoryTree.size() << LL_ENDL; +		warnings++;  	}  	S32 cat_lock = 0;  	S32 item_lock = 0;  	S32 desc_unknown_count = 0;  	S32 version_unknown_count = 0; + +	typedef std::map<LLFolderType::EType, S32> ft_count_map; +	ft_count_map ft_counts_under_root; +	ft_count_map ft_counts_elsewhere; +	 +	// Loop over all categories and check.  	for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)  	{  		const LLUUID& cat_id = cit->first;  		const LLViewerInventoryCategory *cat = cit->second;  		if (!cat)  		{ -            if (error_count < MAX_VERBOSE_ERRORS) -            { -                LL_WARNS() << "invalid cat" << LL_ENDL; -            } -            error_count++; +			LL_WARNS("Inventory") << "null cat" << LL_ENDL; +			warnings++;  			continue;  		} +		LLUUID topmost_ancestor_id; +		// Will leave as null uuid on failure +		getObjectTopmostAncestor(cat_id, topmost_ancestor_id);  		if (cat_id != cat->getUUID())  		{ -            if (error_count < MAX_VERBOSE_ERRORS) -            { -                LL_WARNS() << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL; -            } -            error_count++; +			LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL; +			warnings++;  		}  		if (cat->getParentUUID().isNull())  		{  			if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID())  			{ -                if (error_count < MAX_VERBOSE_ERRORS) -                { -                    LL_WARNS() << "cat " << cat_id << " has no parent, but is not root (" -                        << getRootFolderID() << ") or library root (" -                        << getLibraryRootFolderID() << ")" << LL_ENDL; -                } +				LL_WARNS("Inventory") << "cat " << cat_id << " has no parent, but is not root (" +									  << getRootFolderID() << ") or library root (" +									  << getLibraryRootFolderID() << ")" << LL_ENDL; +				warnings++;  			}  		}  		cat_array_t* cats; @@ -3807,11 +3917,8 @@ bool LLInventoryModel::validate() const  		getDirectDescendentsOf(cat_id,cats,items);  		if (!cats || !items)  		{ -            if (error_count < MAX_VERBOSE_ERRORS) -            { -                LL_WARNS() << "invalid direct descendents for " << cat_id << LL_ENDL; -            } -            error_count++; +			LL_WARNS("Inventory") << "invalid direct descendents for " << cat_id << LL_ENDL; +			warnings++;  			continue;  		}  		if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) @@ -3820,25 +3927,29 @@ bool LLInventoryModel::validate() const  		}  		else if (cats->size() + items->size() != cat->getDescendentCount())  		{ -            if (error_count < MAX_VERBOSE_ERRORS) -            { -                LL_WARNS() << "invalid desc count for " << cat_id << " name [" << cat->getName() -                    << "] parent " << cat->getParentUUID() -                    << " cached " << cat->getDescendentCount() -                    << " expected " << cats->size() << "+" << items->size() -                    << "=" << cats->size() + items->size() << LL_ENDL; -            } -            error_count++; +			// In the case of library this is not unexpected, since +			// different user accounts may be getting the library +			// contents from different inventory hosts. +			if (topmost_ancestor_id.isNull() || topmost_ancestor_id != getLibraryRootFolderID()) +			{ +				LL_WARNS("Inventory") << "invalid desc count for " << cat_id << " [" << getFullPath(cat) << "]" +									  << " cached " << cat->getDescendentCount() +									  << " expected " << cats->size() << "+" << items->size() +									  << "=" << cats->size() +items->size() << LL_ENDL; +				warnings++; +			}  		}  		if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)  		{  			version_unknown_count++;  		} -		if (mCategoryLock.count(cat_id)) +		auto cat_lock_it = mCategoryLock.find(cat_id); +		if (cat_lock_it != mCategoryLock.end() && cat_lock_it->second)  		{  			cat_lock++;  		} -		if (mItemLock.count(cat_id)) +		auto item_lock_it = mItemLock.find(cat_id); +		if (item_lock_it != mItemLock.end() && item_lock_it->second)  		{  			item_lock++;  		} @@ -3848,11 +3959,8 @@ bool LLInventoryModel::validate() const  			if (!item)  			{ -                if (error_count < MAX_VERBOSE_ERRORS) -                { -                    LL_WARNS() << "null item at index " << i << " for cat " << cat_id << LL_ENDL; -                } -                error_count++; +				LL_WARNS("Inventory") << "null item at index " << i << " for cat " << cat_id << LL_ENDL; +				warnings++;  				continue;  			} @@ -3860,13 +3968,10 @@ bool LLInventoryModel::validate() const  			if (item->getParentUUID() != cat_id)  			{ -                if (error_count < MAX_VERBOSE_ERRORS) -                { -                    LL_WARNS() << "wrong parent for " << item_id << " found " -                        << item->getParentUUID() << " expected " << cat_id -                        << LL_ENDL; -                } -                error_count++; +				LL_WARNS("Inventory") << "wrong parent for " << item_id << " found " +									  << item->getParentUUID() << " expected " << cat_id +									  << LL_ENDL; +				warnings++;  			} @@ -3874,24 +3979,17 @@ bool LLInventoryModel::validate() const  			item_map_t::const_iterator it = mItemMap.find(item_id);  			if (it == mItemMap.end())  			{ - -                if (error_count < MAX_VERBOSE_ERRORS) -                { -                    LL_WARNS() << "item " << item_id << " found as child of " -                        << cat_id << " but not in top level mItemMap" << LL_ENDL; -                } -                error_count++; +				LL_WARNS("Inventory") << "item " << item_id << " found as child of " +									  << cat_id << " but not in top level mItemMap" << LL_ENDL; +				warnings++;  			}  			else  			{  				LLViewerInventoryItem *top_item = it->second;  				if (top_item != item)  				{ -                    if (error_count < MAX_VERBOSE_ERRORS) -                    { -                        LL_WARNS() << "item mismatch, item_id " << item_id -                            << " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL; -                    } +					LL_WARNS("Inventory") << "item mismatch, item_id " << item_id +										  << " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL;  				}  			} @@ -3900,25 +3998,19 @@ bool LLInventoryModel::validate() const  			bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);  			if (!found)  			{ -                if (error_count < MAX_VERBOSE_ERRORS) -                { -                    LL_WARNS() << "unable to find topmost ancestor for " << item_id << LL_ENDL; -                } -                error_count++; +				LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL; +				warnings++;  			}  			else  			{  				if (topmost_ancestor_id != getRootFolderID() &&  					topmost_ancestor_id != getLibraryRootFolderID())  				{ -                    if (error_count < MAX_VERBOSE_ERRORS) -                    { -                        LL_WARNS() << "unrecognized top level ancestor for " << item_id -                            << " got " << topmost_ancestor_id -                            << " expected " << getRootFolderID() -                            << " or " << getLibraryRootFolderID() << LL_ENDL; -                    } -                    error_count++; +					LL_WARNS("Inventory") << "unrecognized top level ancestor for " << item_id +										  << " got " << topmost_ancestor_id +										  << " expected " << getRootFolderID() +										  << " or " << getLibraryRootFolderID() << LL_ENDL; +					warnings++;  				}  			}  		} @@ -3932,12 +4024,9 @@ bool LLInventoryModel::validate() const  			getDirectDescendentsOf(parent_id,cats,items);  			if (!cats)  			{ -                if (error_count < MAX_VERBOSE_ERRORS) -                { -                    LL_WARNS() << "cat " << cat_id << " name [" << cat->getName() -                        << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL; -                } -                error_count++; +				LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName() +									  << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL; +				warnings++;  			}  			else  			{ @@ -3953,49 +4042,66 @@ bool LLInventoryModel::validate() const  				}  				if (!found)  				{ -                    if (error_count < MAX_VERBOSE_ERRORS) -                    { -                        LL_WARNS() << "cat " << cat_id << " name [" << cat->getName() -                            << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL; -                    } +					LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName() +										  << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL; +				} +			} +		} + +		// Update count of preferred types +		LLFolderType::EType folder_type = cat->getPreferredType(); +		bool cat_is_in_library = false; +		LLUUID topmost_id; +		if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) && topmost_id == getLibraryRootFolderID()) +		{ +			cat_is_in_library = true; +		} +		if (!cat_is_in_library) +		{ +			if (getRootFolderID().notNull() && (cat->getUUID()==getRootFolderID() || cat->getParentUUID()==getRootFolderID())) +			{ +				ft_counts_under_root[folder_type]++; +				if (folder_type != LLFolderType::FT_NONE) +				{ +					LL_DEBUGS("Inventory") << "Under root cat: " << getFullPath(cat) << " folder_type " << folder_type << LL_ENDL; +				} +			} +			else +			{ +				ft_counts_elsewhere[folder_type]++; +				if (folder_type != LLFolderType::FT_NONE) +				{ +					LL_DEBUGS("Inventory") << "Elsewhere cat: " << getFullPath(cat) << " folder_type " << folder_type << LL_ENDL;  				}  			}  		}  	} +	// Loop over all items and check  	for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)  	{  		const LLUUID& item_id = iit->first;  		LLViewerInventoryItem *item = iit->second;  		if (item->getUUID() != item_id)  		{ -            if (error_count < MAX_VERBOSE_ERRORS) -            { -                LL_WARNS() << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL; -            } -            error_count++; +			LL_WARNS("Inventory") << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL; +			warnings++;  		}  		const LLUUID& parent_id = item->getParentUUID();  		if (parent_id.isNull())  		{ -            if (error_count < MAX_VERBOSE_ERRORS) -            { -                LL_WARNS() << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL; -            } +			LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;  		} -		else if (error_count < MAX_VERBOSE_ERRORS) +		else  		{  			cat_array_t* cats;  			item_array_t* items;  			getDirectDescendentsOf(parent_id,cats,items);  			if (!items)  			{ -                if (error_count < MAX_VERBOSE_ERRORS) -                { -                    LL_WARNS() << "item " << item_id << " name [" << item->getName() -                        << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL; -                } +				LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() +									  << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;  			}  			else  			{ @@ -4010,89 +4116,170 @@ bool LLInventoryModel::validate() const  				}  				if (!found)  				{ -                    if (error_count < MAX_VERBOSE_ERRORS) -                    { -                        LL_WARNS() << "item " << item_id << " name [" << item->getName() -                            << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL; -                    } +					LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() +										  << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;  				}  			}  		} -  		// Link checking -        if (error_count < MAX_VERBOSE_ERRORS) -        { -            if (item->getIsLinkType()) -            { -                const LLUUID& link_id = item->getUUID(); -                const LLUUID& target_id = item->getLinkedUUID(); -                LLViewerInventoryItem *target_item = getItem(target_id); -                LLViewerInventoryCategory *target_cat = getCategory(target_id); -                // Linked-to UUID should have back reference to this link. -                if (!hasBacklinkInfo(link_id, target_id)) -                { -                    LL_WARNS() << "link " << item->getUUID() << " type " << item->getActualType() -                        << " missing backlink info at target_id " << target_id -                        << LL_ENDL; -                } -                // Links should have referents. -                if (item->getActualType() == LLAssetType::AT_LINK && !target_item) -                { -                    LL_WARNS() << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL; -                } -                else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat) -                { -                    LL_WARNS() << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL; -                } -                if (target_item && target_item->getIsLinkType()) -                { -                    LL_WARNS() << "link " << item->getName() << " references a link item " -                        << target_item->getName() << " " << target_item->getUUID() << LL_ENDL; -                } - -                // Links should not have backlinks. -                std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id); -                if (range.first != range.second) -                { -                    LL_WARNS() << "Link item " << item->getName() << " has backlinks!" << LL_ENDL; -                } -            } -            else -            { -                // Check the backlinks of a non-link item. -                const LLUUID& target_id = item->getUUID(); -                std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(target_id); -                for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it) -                { -                    const LLUUID& link_id = it->second; -                    LLViewerInventoryItem *link_item = getItem(link_id); -                    if (!link_item || !link_item->getIsLinkType()) -                    { -                        LL_WARNS() << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL; -                    } -                } -            } -        } +		if (item->getIsLinkType()) +		{ +			const LLUUID& link_id = item->getUUID(); +			const LLUUID& target_id = item->getLinkedUUID(); +			LLViewerInventoryItem *target_item = getItem(target_id); +			LLViewerInventoryCategory *target_cat = getCategory(target_id); +			// Linked-to UUID should have back reference to this link. +			if (!hasBacklinkInfo(link_id, target_id)) +			{ +				LL_WARNS("Inventory") << "link " << item->getUUID() << " type " << item->getActualType() +									  << " missing backlink info at target_id " << target_id +									  << LL_ENDL; +			} +			// Links should have referents. +			if (item->getActualType() == LLAssetType::AT_LINK && !target_item) +			{ +				LL_WARNS("Inventory") << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL; +			} +			else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat) +			{ +				LL_WARNS("Inventory") << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL; +			} +			if (target_item && target_item->getIsLinkType()) +			{ +				LL_WARNS("Inventory") << "link " << item->getName() << " references a link item " +									  << target_item->getName() << " " << target_item->getUUID() << LL_ENDL; +			} + +			// Links should not have backlinks. +			std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id); +			if (range.first != range.second) +			{ +				LL_WARNS("Inventory") << "Link item " << item->getName() << " has backlinks!" << LL_ENDL; +			} +		} +		else +		{ +			// Check the backlinks of a non-link item. +			const LLUUID& target_id = item->getUUID(); +			std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(target_id); +			for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it) +			{ +				const LLUUID& link_id = it->second; +				LLViewerInventoryItem *link_item = getItem(link_id); +				if (!link_item || !link_item->getIsLinkType()) +				{ +					LL_WARNS("Inventory") << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL; +				} +			} +		}  	} -	 + +	// Check system folders +	for (auto fit=ft_counts_under_root.begin(); fit != ft_counts_under_root.end(); ++fit) +	{ +		LL_DEBUGS("Inventory") << "Folder type " << fit->first << " count " << fit->second << " under root" << LL_ENDL; +	} +	for (auto fit=ft_counts_elsewhere.begin(); fit != ft_counts_elsewhere.end(); ++fit) +	{ +		LL_DEBUGS("Inventory") << "Folder type " << fit->first << " count " << fit->second << " elsewhere" << LL_ENDL; +	} + +	static LLCachedControl<bool> fake_system_folder_issues(gSavedSettings, "QAModeFakeSystemFolderIssues", false); +	static std::default_random_engine e{}; +    static std::uniform_int_distribution<> distrib(0, 1); +	for (S32 ft=LLFolderType::FT_TEXTURE; ft<LLFolderType::FT_COUNT; ft++) +	{ +		LLFolderType::EType folder_type = static_cast<LLFolderType::EType>(ft); +		if (LLFolderType::lookup(folder_type)==LLFolderType::badLookup()) +		{ +			continue; +		} +		bool is_automatic = LLFolderType::lookupIsAutomaticType(folder_type); +		bool is_singleton = LLFolderType::lookupIsSingletonType(folder_type); +		S32 count_under_root = ft_counts_under_root[folder_type]; +		S32 count_elsewhere = ft_counts_elsewhere[folder_type]; +		if (fake_system_folder_issues) +		{ +			// Force all counts to be either 0 or 2, thus flagged as an error. +			count_under_root = 2*distrib(e);  +			count_elsewhere = 2*distrib(e); +			validation_info->mFatalQADebugMode = true; +		} +		if (is_singleton) +		{ +			if (count_under_root==0) +			{ +				LL_WARNS("Inventory") << "Expected system folder type " << ft << " was not found under root" << LL_ENDL; +				// Need to create, if allowed. +				if (is_automatic) +				{ +					LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL; +					fatalities++; +					validation_info->mMissingRequiredSystemFolders.insert(LLFolderType::EType(ft)); +				} +				else +				{ +					// Can create, and will when needed. +					warnings++; +				} +			} +			else if (count_under_root > 1) +			{ +				LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL; +				validation_info->mDuplicateRequiredSystemFolders.insert(LLFolderType::EType(ft)); +				fatalities++; +			} +			if (count_elsewhere > 0) +			{ +				LL_WARNS("Inventory") << "Found " << count_elsewhere << " extra folders of type " << ft << " outside of root" << LL_ENDL; +				warnings++; +			} +		} +	} + +  	if (cat_lock > 0 || item_lock > 0)  	{ -		LL_INFOS() << "Found locks on some categories: sub-cat arrays " +		LL_INFOS("Inventory") << "Found locks on some categories: sub-cat arrays "  				<< cat_lock << ", item arrays " << item_lock << LL_ENDL;  	}  	if (desc_unknown_count != 0)  	{ -		LL_INFOS() << "Found " << desc_unknown_count << " cats with unknown descendent count" << LL_ENDL;  +		LL_DEBUGS() << "Found " << desc_unknown_count << " cats with unknown descendent count" << LL_ENDL;   	}  	if (version_unknown_count != 0)  	{ -		LL_INFOS() << "Found " << version_unknown_count << " cats with unknown version" << LL_ENDL; +		LL_DEBUGS("Inventory") << "Found " << version_unknown_count << " cats with unknown version" << LL_ENDL;  	} -	LL_INFOS() << "Validate done, found " << error_count << " errors" << LL_ENDL; +	// FIXME need to fail login and tell user to retry, contact support if problem persists. +	bool valid = (fatalities == 0); +	LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatalities << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL; -	return error_count == 0; +	validation_info->mFatalErrorCount = fatalities; +	validation_info->mWarningCount = warnings; + +	return validation_info;  +} + +// Provides a unix-style path from root, like "/My Inventory/Clothing/.../myshirt" +std::string LLInventoryModel::getFullPath(const LLInventoryObject *obj) const +{ +	std::vector<std::string> path_elts; +	std::map<LLUUID,bool> visited; +	while (obj != NULL && !visited[obj->getUUID()]) +	{ +		path_elts.push_back(obj->getName()); +		// avoid infinite loop in the unlikely event of a cycle +		visited[obj->getUUID()] = true; +		obj = getObject(obj->getParentUUID()); +	} +	std::stringstream s; +	std::string delim("/"); +	std::reverse(path_elts.begin(), path_elts.end()); +	std::string result = "/" + boost::algorithm::join(path_elts, delim); +	return result;  }  ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 4dcd9332be..e81652820f 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -55,7 +55,29 @@ class LLInventoryCategory;  class LLMessageSystem;  class LLInventoryCollectFunctor; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +///---------------------------------------------------------------------------- +/// LLInventoryValidationInfo  +///---------------------------------------------------------------------------- +class LLInventoryValidationInfo: public LLRefCount +{ +public: +	LLInventoryValidationInfo(); +	void toOstream(std::ostream& os) const; +	void asLLSD(LLSD& sd) const; +	 + +	S32 mFatalErrorCount; +	S32 mWarningCount; +	bool mInitialized; +	bool mFatalNoRootFolder; +	bool mFatalNoLibraryRootFolder; +	bool mFatalQADebugMode; +	std::set<LLFolderType::EType> mMissingRequiredSystemFolders; +	std::set<LLFolderType::EType> mDuplicateRequiredSystemFolders; +}; +std::ostream& operator<<(std::ostream& s, const LLInventoryValidationInfo& v); + +///----------------------------------------------------------------------------  // LLInventoryModel  //  // Represents a collection of inventory, and provides efficient ways to access  @@ -63,7 +85,7 @@ class LLInventoryCollectFunctor;  //   NOTE: This class could in theory be used for any place where you need   //   inventory, though it optimizes for time efficiency - not space efficiency,   //   probably making it inappropriate for use on tasks. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +///----------------------------------------------------------------------------  class LLInventoryModel  {  	LOG_CLASS(LLInventoryModel); @@ -660,7 +682,9 @@ private:  	//--------------------------------------------------------------------  public:  	void dumpInventory() const; -	bool validate() const; +	LLPointer<LLInventoryValidationInfo> validate() const; +	LLPointer<LLInventoryValidationInfo> mValidationInfo; +	std::string getFullPath(const LLInventoryObject *obj) const;  /**                    Miscellaneous   **                                                                            ** diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 7c241c3283..6b102c7500 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -284,17 +284,18 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  	mCompletionObserver = new LLInvPanelComplObserver(boost::bind(&LLInventoryPanel::onItemsCompletion, this));  	mInventory->addObserver(mCompletionObserver); -    if (mBuildViewsOnInit) +    if (mBuildViewsOnInit && mViewsInitialized == VIEWS_UNINITIALIZED)      {          // Build view of inventory if we need default full hierarchy and inventory is ready, otherwise do in onIdle.          // Initializing views takes a while so always do it onIdle if viewer already loaded. -        if (mInventory->isInventoryUsable() -            && mViewsInitialized == VIEWS_UNINITIALIZED +        if (mInventory->isInventoryUsable()                          && LLStartUp::getStartupState() <= STATE_WEARABLES_WAIT)          { -            initializeViews(); +            // Usually this happens on login, so we have less time constraits, but too long and we can cause a disconnect +            const F64 max_time = 20.f; +            initializeViews(max_time);          } -        else if (mViewsInitialized != VIEWS_INITIALIZING) +        else          {              mViewsInitialized = VIEWS_INITIALIZING;              gIdleCallbacks.addFunction(onIdle, (void*)this); @@ -499,6 +500,19 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve  		view_folder = dynamic_cast<LLFolderViewFolder*>(view_item);  	} +    // if folder is not fully initialized (likely due to delayed load on idle) +    // and we are not rebuilding, try updating children +    if (view_folder +        && !view_folder->areChildrenInited() +        && ( (mask & LLInventoryObserver::REBUILD) == 0)) +    { +        LLInventoryObject const* objectp = mInventory->getObject(item_id); +        if (objectp) +        { +            view_item = buildNewViews(item_id, objectp, view_item, BUILD_ONE_FOLDER); +        } +    } +  	//////////////////////////////  	// LABEL Operation  	// Empty out the display name for relabel. @@ -539,7 +553,7 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve          if (objectp)          {              // providing NULL directly avoids unnessesary getItemByID calls -            view_item = buildNewViews(item_id, objectp, NULL); +            view_item = buildNewViews(item_id, objectp, NULL, BUILD_ONE_FOLDER);          }          else          { @@ -592,7 +606,7 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve              if (objectp)              {                  // providing NULL directly avoids unnessesary getItemByID calls -                buildNewViews(item_id, objectp, NULL); +                buildNewViews(item_id, objectp, NULL, BUILD_ONE_FOLDER);              }  			// Select any newly created object that has the auto rename at top of folder root set. @@ -743,12 +757,12 @@ void LLInventoryPanel::onIdle(void *userdata)  		return;  	LLInventoryPanel *self = (LLInventoryPanel*)userdata; -	// Inventory just initialized, do complete build -	if (self->mViewsInitialized != VIEWS_INITIALIZED) +	if (self->mViewsInitialized <= VIEWS_INITIALIZING)  	{ -		self->initializeViews(); +		const F64 max_time = 0.001f; // 1 ms, in this case we need only root folders +		self->initializeViews(max_time); // Shedules LLInventoryPanel::idle()  	} -	if (self->mViewsInitialized == VIEWS_INITIALIZED) +	if (self->mViewsInitialized >= VIEWS_BUILDING)  	{  		gIdleCallbacks.deleteFunction(onIdle, (void*)self);  	} @@ -783,6 +797,49 @@ void LLInventoryPanel::idle(void* user_data)  	} +    bool in_visible_chain = panel->isInVisibleChain(); + +    if (!panel->mBuildViewsQueue.empty()) +    { +        const F64 max_time = in_visible_chain ? 0.006f : 0.001f; // 6 ms +        F64 curent_time = LLTimer::getTotalSeconds(); +        panel->mBuildViewsEndTime = curent_time + max_time; + +        // things added last are closer to root thus of higher priority +        std::deque<LLUUID> priority_list; +        priority_list.swap(panel->mBuildViewsQueue); + +        while (curent_time < panel->mBuildViewsEndTime +            && !priority_list.empty()) +        { +            LLUUID item_id = priority_list.back(); +            priority_list.pop_back(); + +            LLInventoryObject const* objectp = panel->mInventory->getObject(item_id); +            if (objectp && panel->typedViewsFilter(item_id, objectp)) +            { +                LLFolderViewItem* folder_view_item = panel->getItemByID(item_id); +                if (!folder_view_item || !folder_view_item->areChildrenInited()) +                { +                    const LLUUID &parent_id = objectp->getParentUUID(); +                    LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)panel->getItemByID(parent_id); +                    panel->buildViewsTree(item_id, parent_id, objectp, folder_view_item, parent_folder, BUILD_TIMELIMIT); +                } +            } +            curent_time = LLTimer::getTotalSeconds(); +        } +        while (!priority_list.empty()) +        { +            // items in priority_list are of higher priority +            panel->mBuildViewsQueue.push_back(priority_list.front()); +            priority_list.pop_front(); +        } +        if (panel->mBuildViewsQueue.empty()) +        { +            panel->mViewsInitialized = VIEWS_INITIALIZED; +        } +    } +      // Take into account the fact that the root folder might be invalidated      if (panel->mFolderRoot.get())      { @@ -813,10 +870,16 @@ void LLInventoryPanel::idle(void* user_data)  } -void LLInventoryPanel::initializeViews() +void LLInventoryPanel::initializeViews(F64 max_time)  {  	if (!gInventory.isInventoryUsable()) return; +    mViewsInitialized = VIEWS_BUILDING; + +    F64 curent_time = LLTimer::getTotalSeconds(); +    mBuildViewsEndTime = curent_time + max_time; + +	// init everything  	LLUUID root_id = getRootFolderID();  	if (root_id.notNull())  	{ @@ -824,14 +887,18 @@ void LLInventoryPanel::initializeViews()  	}  	else  	{ -		// Default case: always add "My Inventory" first, "Library" second +		// Default case: always add "My Inventory" root first, "Library" root second +		// If we run out of time, this still should create root folders  		buildNewViews(gInventory.getRootFolderID());		// My Inventory  		buildNewViews(gInventory.getLibraryRootFolderID());	// Library  	} -	gIdleCallbacks.addFunction(idle, this); +    if (mBuildViewsQueue.empty()) +    { +        mViewsInitialized = VIEWS_INITIALIZED; +    } -	mViewsInitialized = VIEWS_INITIALIZED; +	gIdleCallbacks.addFunction(idle, this);  	openStartFolderOrMyInventory(); @@ -910,10 +977,13 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO      LLFolderViewItem* folder_view_item = getItemByID(id);      LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); -    return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder); +    return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder, BUILD_TIMELIMIT);  } -LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryObject const* objectp, LLFolderViewItem *folder_view_item) +LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, +                                                  LLInventoryObject const* objectp, +                                                  LLFolderViewItem *folder_view_item, +                                                  const EBuildModes &mode)  {      if (!objectp)      { @@ -928,14 +998,15 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO      const LLUUID &parent_id = objectp->getParentUUID();      LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); -    return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder); +    return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder, mode);  }  LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id,                                                    const LLUUID& parent_id,                                                    LLInventoryObject const* objectp,                                                    LLFolderViewItem *folder_view_item, -                                                  LLFolderViewFolder *parent_folder) +                                                  LLFolderViewFolder *parent_folder, +                                                  const EBuildModes &mode)  {      // Force the creation of an extra root level folder item if required by the inventory panel (default is "false")      bool allow_drop = true; @@ -1036,9 +1107,64 @@ LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id,          }  	} +    bool create_children = folder_view_item && objectp->getType() == LLAssetType::AT_CATEGORY; + +    if (create_children) +    { +        switch (mode) +        { +            case BUILD_TIMELIMIT: +            { +                F64 curent_time = LLTimer::getTotalSeconds(); +                // If function is out of time, we want to shedule it into mBuildViewsQueue +                // If we have time, no matter how little, create views for all children +                // +                // This creates children in 'bulk' to make sure folder has either +                // 'empty and incomplete' or 'complete' states with nothing in between. +                // Folders are marked as mIsFolderComplete == false by default, +                // later arrange() will update mIsFolderComplete by child count +                if (mBuildViewsEndTime < curent_time) +                { +                    create_children = false; +                    // run it again for the sake of creating children +                    mBuildViewsQueue.push_back(id); +                } +                else +                { +                    create_children = true; +                    folder_view_item->setChildrenInited(true); +                } +                break; +            } +            case BUILD_NO_CHILDREN: +            { +                create_children = false; +                // run it to create children, current caller is only interested in current view +                mBuildViewsQueue.push_back(id); +                break; +            } +            case BUILD_ONE_FOLDER: +            { +                // This view loads chindren, following ones don't +                // Note: Might be better idea to do 'depth' instead, +                // It also will help to prioritize root folder's content +                create_children = true; +                folder_view_item->setChildrenInited(true); +                break; +            } +            case BUILD_NO_LIMIT: +            default: +            { +                // keep working till everything exists +                create_children = true; +                folder_view_item->setChildrenInited(true); +            } +        } +    } +  	// If this is a folder, add the children of the folder and recursively add any   	// child folders. -	if (folder_view_item && objectp->getType() == LLAssetType::AT_CATEGORY) +	if (create_children)  	{  		LLViewerInventoryCategory::cat_array_t* categories;  		LLViewerInventoryItem::item_array_t* items; @@ -1054,7 +1180,7 @@ LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id,  				 ++cat_iter)  			{  				const LLViewerInventoryCategory* cat = (*cat_iter); -                if (typedViewsFilter(cat->getUUID(), cat)) +                if (typedViewsFilter(cat->getUUID(), cat))                   {                      if (has_folders)                      { @@ -1062,11 +1188,11 @@ LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id,                          // each time, especially since content is growing, we can just                          // iter over copy of mItemMap in some way                          LLFolderViewItem* view_itemp = getItemByID(cat->getUUID()); -                        buildViewsTree(cat->getUUID(), id, cat, view_itemp, parentp); +                        buildViewsTree(cat->getUUID(), id, cat, view_itemp, parentp, (mode == BUILD_ONE_FOLDER ? BUILD_NO_CHILDREN : mode));                      }                      else                      { -                        buildViewsTree(cat->getUUID(), id, cat, NULL, parentp); +                        buildViewsTree(cat->getUUID(), id, cat, NULL, parentp, (mode == BUILD_ONE_FOLDER ? BUILD_NO_CHILDREN : mode));                      }                  }  			} @@ -1078,17 +1204,16 @@ LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id,  				 item_iter != items->end();  				 ++item_iter)  			{ +                // At the moment we have to build folder's items in bulk and ignore mBuildViewsEndTime  				const LLViewerInventoryItem* item = (*item_iter);                  if (typedViewsFilter(item->getUUID(), item))                  { -                      // This can be optimized: we don't need to call getItemByID()                      // each time, especially since content is growing, we can just                      // iter over copy of mItemMap in some way                      LLFolderViewItem* view_itemp = getItemByID(item->getUUID()); -                    buildViewsTree(item->getUUID(), id, item, view_itemp, parentp); +                    buildViewsTree(item->getUUID(), id, item, view_itemp, parentp, mode);                  } -  			}  		}  		mInventory->unlockDirectDescendentArrays(id); @@ -1201,6 +1326,18 @@ void LLInventoryPanel::onFocusReceived()  	LLPanel::onFocusReceived();  } +void LLInventoryPanel::onFolderOpening(const LLUUID &id) +{ +    LLFolderViewItem* folder = getItemByID(id); +    if (folder && !folder->areChildrenInited()) +    { +        // Last item in list will be processed first. +        // This might result in dupplicates in list, but it +        // isn't critical, views won't be created twice +        mBuildViewsQueue.push_back(id); +    } +} +  bool LLInventoryPanel::addBadge(LLBadge * badge)  {  	bool badge_added = false; @@ -1222,7 +1359,7 @@ void LLInventoryPanel::openAllFolders()  void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus)  {  	// Don't select objects in COF (e.g. to prevent refocus when items are worn). -	const LLInventoryObject *obj = gInventory.getObject(obj_id); +	const LLInventoryObject *obj = mInventory->getObject(obj_id);  	if (obj && obj->getParentUUID() == LLAppearanceMgr::instance().getCOF())  	{  		return; @@ -1259,6 +1396,12 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it  		if (view_model)  		{  			LLUUID id = view_model->getUUID(); +            if (!(*it)->areChildrenInited()) +            { +                const F64 max_time = 0.0001f; +                mBuildViewsEndTime = LLTimer::getTotalSeconds() + max_time; +                buildNewViews(id); +            }  			LLViewerInventoryItem* inv_item = mInventory->getItem(id);  			if (inv_item && !inv_item->isFinished()) @@ -1715,7 +1858,17 @@ LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id)  void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL    take_keyboard_focus )  {  	LLFolderViewItem* itemp = getItemByID(obj_id); -	if(itemp && itemp->getViewModelItem() && itemp->passedFilter()) + +    if (itemp && !itemp->areChildrenInited()) +    { +        LLInventoryObject const* objectp = mInventory->getObject(obj_id); +        if (objectp) +        { +            buildNewViews(obj_id, objectp, itemp, BUILD_ONE_FOLDER); +        } +    } + +	if(itemp && itemp->getViewModelItem())  	{  		itemp->arrangeAndSet(TRUE, take_keyboard_focus);  		mSelectThisID.setNull(); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index a019fc2231..552c61b915 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -171,6 +171,7 @@ public:  	// LLUICtrl methods  	 /*virtual*/ void onFocusLost();  	 /*virtual*/ void onFocusReceived(); +     void onFolderOpening(const LLUUID &id);  	// LLBadgeHolder methods  	bool addBadge(LLBadge * badge); @@ -318,12 +319,9 @@ private:  	//--------------------------------------------------------------------  public:  	void addHideFolderType(LLFolderType::EType folder_type); - -public: -	bool getViewsInitialized() const { return mViewsInitialized == VIEWS_INITIALIZED; }  protected:  	// Builds the UI.  Call this once the inventory is usable. -	void 				initializeViews(); +	void 				initializeViews(F64 max_time);  	// Specific inventory colors  	static bool                 sColorSetInitialized; @@ -331,13 +329,25 @@ protected:  	static LLUIColor			sDefaultHighlightColor;  	static LLUIColor			sLibraryColor;  	static LLUIColor			sLinkColor; -	 + +    enum EBuildModes +    { +        BUILD_NO_LIMIT, +        BUILD_TIMELIMIT, // requires mBuildViewsEndTime +        BUILD_ONE_FOLDER, +        BUILD_NO_CHILDREN, +    }; + +    // All buildNewViews() use BUILD_TIMELIMIT by default +    // and expect time limit mBuildViewsEndTime to be set  	LLFolderViewItem*			buildNewViews(const LLUUID& id);      LLFolderViewItem*			buildNewViews(const LLUUID& id,                                                LLInventoryObject const* objectp);      LLFolderViewItem*			buildNewViews(const LLUUID& id,                                                LLInventoryObject const* objectp, -                                              LLFolderViewItem *target_view); +                                              LLFolderViewItem *target_view, +                                              const EBuildModes &mode = BUILD_TIMELIMIT); +      // if certain types are not allowed, no reason to create views      virtual bool				typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) { return true; } @@ -354,17 +364,21 @@ private:                                                const LLUUID& parent_id,                                                LLInventoryObject const* objectp,                                                LLFolderViewItem *target_view, -                                              LLFolderViewFolder *parent_folder_view); +                                              LLFolderViewFolder *parent_folder_view, +                                              const EBuildModes &mode);      typedef enum e_views_initialization_state      {          VIEWS_UNINITIALIZED = 0,          VIEWS_INITIALIZING, +        VIEWS_BUILDING, // Root folder exists          VIEWS_INITIALIZED,      } EViewsInitializationState;  	bool						mBuildViewsOnInit;      EViewsInitializationState	mViewsInitialized; // Whether views have been generated +    F64							mBuildViewsEndTime; // Stop building views past this timestamp +    std::deque<LLUUID>			mBuildViewsQueue;  };  /************************************************************************/ diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index d7a17b237e..c1e5e5faed 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -619,74 +619,11 @@ void LLKeyConflictHandler::saveToSettings(bool temporary)          }      } -#if 1 -    // Legacy support -    // Remove #if-#endif section half a year after DRTVWR-501 releases. -    // Update legacy settings in settings.xml -    // We only care for third person view since legacy settings can't store -    // more than one mode. -    // We are saving this even if we are in temporary mode - preferences -    // will restore values on cancel -    if (mLoadMode == MODE_THIRD_PERSON && mHasUnsavedChanges) -    { -        bool value = canHandleMouse("walk_to", CLICK_DOUBLELEFT, MASK_NONE); -        gSavedSettings.setBOOL("DoubleClickAutoPilot", value); - -        value = canHandleMouse("walk_to", CLICK_LEFT, MASK_NONE); -        gSavedSettings.setBOOL("ClickToWalk", value); - -        // new method can save both toggle and push-to-talk values simultaneously, -        // but legacy one can save only one. It also doesn't support mask. -        LLKeyData data = getControl("toggle_voice", 0); -        bool can_toggle = !data.isEmpty(); -        if (!can_toggle) -        { -            data = getControl("voice_follow_key", 0); -        } - -        gSavedSettings.setBOOL("PushToTalkToggle", can_toggle); -        if (data.isEmpty()) -        { -            // legacy viewer has a bug that might crash it if NONE value is assigned. -            // just reset to default -            gSavedSettings.getControl("PushToTalkButton")->resetToDefault(false); -        } -        else -        { -            if (data.mKey != KEY_NONE) -            { -                gSavedSettings.setString("PushToTalkButton", LLKeyboard::stringFromKey(data.mKey)); -            } -            else -            { -                std::string ctrl_value; -                switch (data.mMouse) -                { -                case CLICK_MIDDLE: -                    ctrl_value = "MiddleMouse"; -                    break; -                case CLICK_BUTTON4: -                    ctrl_value = "MouseButton4"; -                    break; -                case CLICK_BUTTON5: -                    ctrl_value = "MouseButton5"; -                    break; -                default: -                    ctrl_value = "MiddleMouse"; -                    break; -                } -                gSavedSettings.setString("PushToTalkButton", ctrl_value); -            } -        } -    } -#endif -      if (mLoadMode == MODE_THIRD_PERSON && mHasUnsavedChanges)      {          // Map floater should react to doubleclick if doubleclick for teleport is set -        // Todo: Seems conterintuitive for map floater to share inworld controls -        // after these changes release, discuss with UI UX engineer if this should just -        // be set to 1 by default (before release this also doubles as legacy support) +        // Todo: Seems conterintuitive for map floater to share inworld controls, +        // discuss with UI UX engineer if this should just be set to 1 by default          bool value = canHandleMouse("teleport_to", CLICK_DOUBLELEFT, MASK_NONE);          gSavedSettings.setBOOL("DoubleClickTeleport", value);      } diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp index 89eb941106..583742f970 100644 --- a/indra/newview/llmachineid.cpp +++ b/indra/newview/llmachineid.cpp @@ -466,7 +466,7 @@ S32 LLMachineID::init()          }      }  #else -    unsigned char * staticPtr = (unsigned char *)(&static_legacy_id[0]); +    unsigned char * staticPtr = (unsigned char *)(&static_unique_id[0]);      ret_code = LLUUID::getNodeID(staticPtr);      has_static_unique_id = true;      has_static_legacy_id = false; diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 452762b09d..d85a846f4d 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1543,7 +1543,10 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )  				LLVector3 object_axis;  				getObjectAxisClosestToMouse(object_axis); -				object_axis = object_axis * first_object_node->mSavedRotation; +                if (first_object_node) +                { +                    object_axis = object_axis * first_object_node->mSavedRotation; +                }  				// project onto constraint plane  				object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index aa0c7fb73b..044c76ce2c 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -1025,6 +1025,12 @@ void LLMarketplaceData::createSLMListingCoro(LLUUID folderId, LLUUID versionId,      log_SLM_infos("Post /listings", status.getType(), result); +    if (!result.has("listings") || !result["listings"].isArray() || result["listings"].size() == 0) +    { +        LL_INFOS("SLM") << "Received an empty response for folder " << folderId << LL_ENDL; +        return; +    } +      // Extract the info from the results      for (LLSD::array_iterator it = result["listings"].beginArray();          it != result["listings"].endArray(); ++it) @@ -1092,6 +1098,19 @@ void LLMarketplaceData::updateSLMListingCoro(LLUUID folderId, S32 listingId, LLU      log_SLM_infos("Put /listing", status.getType(), result); +    if (!result.has("listings") || !result["listings"].isArray() || result["listings"].size() == 0) +    { +        LL_INFOS("SLM") << "Received an empty response for listing " << listingId << " folder " << folderId << LL_ENDL; +        // Try to get listing more directly after a delay +        const float FORCE_UPDATE_TIMEOUT = 5.0; +        llcoro::suspendUntilTimeout(FORCE_UPDATE_TIMEOUT); +        if (!LLApp::isExiting() && LLMarketplaceData::instanceExists()) +        { +            getSLMListing(listingId); +        } +        return; +    } +      // Extract the info from the Json string      for (LLSD::array_iterator it = result["listings"].beginArray();          it != result["listings"].endArray(); ++it) diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 0affe8efb4..5393d0b0b7 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -46,6 +46,7 @@  #include "lluictrlfactory.h"	// LLDefaultChildRegistry  #include "llkeyboard.h"  #include "llviewermenu.h" +#include "llviewermenufile.h" // LLFilePickerThread  // linden library includes  #include "llfocusmgr.h" @@ -105,7 +106,8 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :  	mTrusted(p.trusted_content),  	mWindowShade(NULL),  	mHoverTextChanged(false), -	mContextMenu(NULL) +	mContextMenu(NULL), +    mAllowFileDownload(false)  {  	{  		LLColor4 color = p.caret_color().get(); @@ -1129,8 +1131,23 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)  		case MEDIA_EVENT_FILE_DOWNLOAD:  		{ -			//llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl; -			//LLNotificationsUtil::add("MediaFileDownloadUnsupported"); +            if (mAllowFileDownload) +            { +                // pick a file from SAVE FILE dialog +                // for now the only thing that should be allowed to save is 360s +                std::string suggested_filename = self->getFileDownloadFilename(); +                LLFilePicker::ESaveFilter filter = LLFilePicker::FFSAVE_ALL; +                if (suggested_filename.find(".jpg") != std::string::npos || suggested_filename.find(".jpeg") != std::string::npos) +                    filter = LLFilePicker::FFSAVE_JPEG; +                if (suggested_filename.find(".png") != std::string::npos) +                    filter = LLFilePicker::FFSAVE_PNG; + +                (new LLMediaFilePicker(self, filter, suggested_filename))->getFile(); +            } +            else +            { +                LLNotificationsUtil::add("MediaFileDownloadUnsupported"); +            }  		};  		break; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index bd24c47a4f..bc4cbaae68 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -151,6 +151,8 @@ public:  		void setTrustedContent(bool trusted); +        void setAllowFileDownload(bool allow) { mAllowFileDownload = allow; } +  		// over-rides  		virtual BOOL handleKeyHere( KEY key, MASK mask);  		virtual BOOL handleKeyUpHere(KEY key, MASK mask); @@ -205,7 +207,8 @@ public:  				mClearCache,  				mHoverTextChanged,  				mDecoupleTextureSize, -				mUpdateScrolls; +				mUpdateScrolls, +                mAllowFileDownload;  		std::string mHomePageUrl,  					mHomePageMimeType, diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 5d81d2c9b3..b9fcad6366 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -221,27 +221,14 @@ LLModelPreview::~LLModelPreview()      }  } -U32 LLModelPreview::calcResourceCost() +void LLModelPreview::updateDimentionsAndOffsets()  {      assert_main_thread();      rebuildUploadData(); -    //Upload skin is selected BUT check to see if the joints coming in from the asset were malformed. -    if (mFMP && mFMP->childGetValue("upload_skin").asBoolean()) -    { -        bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean(); -        if (uploadingJointPositions && !isRigValidForJointPositionUpload()) -        { -            mFMP->childDisable("ok_btn"); -        } -    } -      std::set<LLModel*> accounted; -    U32 num_points = 0; -    U32 num_hulls = 0; -    F32 debug_scale = mFMP ? mFMP->childGetValue("import_scale").asReal() : 1.f;      mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 3.0f;      if (mFMP && mFMP->childGetValue("upload_joints").asBoolean()) @@ -253,8 +240,6 @@ U32 LLModelPreview::calcResourceCost()          getPreviewAvatar()->addPelvisFixup(mPelvisZOffset, fake_mesh_id);      } -    F32 streaming_cost = 0.f; -    F32 physics_cost = 0.f;      for (U32 i = 0; i < mUploadData.size(); ++i)      {          LLModelInstance& instance = mUploadData[i]; @@ -263,11 +248,6 @@ U32 LLModelPreview::calcResourceCost()          {              accounted.insert(instance.mModel); -            LLModel::Decomposition& decomp = -                instance.mLOD[LLModel::LOD_PHYSICS] ? -                instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics : -                instance.mModel->mPhysics; -              //update instance skin info for each lods pelvisZoffset               for (int j = 0; j<LLModel::NUM_LODS; ++j)              { @@ -276,58 +256,14 @@ U32 LLModelPreview::calcResourceCost()                      instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset;                  }              } - -            std::stringstream ostr; -            LLSD ret = LLModel::writeModel(ostr, -                instance.mLOD[4], -                instance.mLOD[3], -                instance.mLOD[2], -                instance.mLOD[1], -                instance.mLOD[0], -                decomp, -                mFMP->childGetValue("upload_skin").asBoolean(), -                mFMP->childGetValue("upload_joints").asBoolean(), -                mFMP->childGetValue("lock_scale_if_joint_position").asBoolean(), -                TRUE, -                FALSE, -                instance.mModel->mSubmodelID); - -            num_hulls += decomp.mHull.size(); -            for (U32 i = 0; i < decomp.mHull.size(); ++i) -            { -                num_points += decomp.mHull[i].size(); -            } - -            //calculate streaming cost -            LLMatrix4 transformation = instance.mTransform; - -            LLVector3 position = LLVector3(0, 0, 0) * transformation; - -            LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position; -            LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position; -            LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position; -            F32 x_length = x_transformed.normalize(); -            F32 y_length = y_transformed.normalize(); -            F32 z_length = z_transformed.normalize(); -            LLVector3 scale = LLVector3(x_length, y_length, z_length); - -            F32 radius = scale.length()*0.5f*debug_scale; - -            LLMeshCostData costs; -            if (gMeshRepo.getCostData(ret, costs)) -            { -                streaming_cost += costs.getRadiusBasedStreamingCost(radius); -            }          }      }      F32 scale = mFMP ? mFMP->childGetValue("import_scale").asReal()*2.f : 2.f; -    mDetailsSignal(mPreviewScale[0] * scale, mPreviewScale[1] * scale, mPreviewScale[2] * scale, streaming_cost, physics_cost); +    mDetailsSignal((F32)(mPreviewScale[0] * scale), (F32)(mPreviewScale[1] * scale), (F32)(mPreviewScale[2] * scale));      updateStatusMessages(); - -    return (U32)streaming_cost;  }  void LLModelPreview::rebuildUploadData() @@ -2703,9 +2639,8 @@ void LLModelPreview::update()      if (mDirty && mLodsQuery.empty())      {          mDirty = false; -        mResourceCost = calcResourceCost(); +        updateDimentionsAndOffsets();          refresh(); -        updateStatusMessages();      }  } @@ -2974,8 +2909,6 @@ BOOL LLModelPreview::render()                  {                      // auto enable weight upload if weights are present                      // (note: all these UI updates need to be somewhere that is not render) -                    mViewOption["show_skin_weight"] = true; -                    skin_weight = true;                      fmp->childSetValue("upload_skin", true);                      mFirstSkinUpdate = false;                  } diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 48d6d362eb..f78f476810 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -115,7 +115,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex  {      LOG_CLASS(LLModelPreview); -    typedef boost::signals2::signal<void(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)> details_signal_t; +    typedef boost::signals2::signal<void(F32 x, F32 y, F32 z)> details_signal_t;      typedef boost::signals2::signal<void(void)> model_loaded_signal_t;      typedef boost::signals2::signal<void(bool)> model_updated_signal_t; @@ -166,7 +166,7 @@ public:      void genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 decimation = 3, bool enforce_tri_limit = false);      void generateNormals();      void restoreNormals(); -    U32 calcResourceCost(); +    void updateDimentionsAndOffsets();      void rebuildUploadData();      void saveUploadData(bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position);      void saveUploadData(const std::string& filename, bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position); @@ -254,7 +254,6 @@ protected:      LLVector3	mPreviewScale;      S32			mPreviewLOD;      S32			mPhysicsSearchLOD; -    U32			mResourceCost;      std::string mLODFile[LLModel::NUM_LODS];      bool		mLoading;      U32			mLoadState; diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index c24c74393d..e3ef407f76 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -410,6 +410,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(  	if (cell)  	{  		cell->setValue(prefix + fullname); +		cell->setAltValue(name_item.alt_value());  	}  	dirtyColumns(); diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 58a9b01a45..90b9cdc133 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -69,7 +69,7 @@ void LLAlertHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLAlertHandler::processNotification(const LLNotificationPtr& notification) +bool LLAlertHandler::processNotification(const LLNotificationPtr& notification, bool should_log)  {  	if(mChannel.isDead())  	{ @@ -131,7 +131,7 @@ LLViewerAlertHandler::LLViewerAlertHandler(const std::string& name, const std::s  {  } -bool LLViewerAlertHandler::processNotification(const LLNotificationPtr& p) +bool LLViewerAlertHandler::processNotification(const LLNotificationPtr& p, bool should_log)  {  	if (gHeadlessClient)  	{ diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 8fef102cf8..f87ebf219b 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -62,7 +62,7 @@ void LLGroupHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLGroupHandler::processNotification(const LLNotificationPtr& notification) +bool LLGroupHandler::processNotification(const LLNotificationPtr& notification, bool should_log)  {  	if(mChannel.isDead())  	{ diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index ef4aced2c7..ddc957c941 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -96,10 +96,10 @@ public:  	// base interface functions  	virtual void onAdd(LLNotificationPtr p) { processNotification(p); }  	virtual void onChange(LLNotificationPtr p) { processNotification(p); } -	virtual void onLoad(LLNotificationPtr p) { processNotification(p); } +	virtual void onLoad(LLNotificationPtr p) { processNotification(p, false); }  	virtual void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} -	virtual bool processNotification(const LLNotificationPtr& notify) = 0; +	virtual bool processNotification(const LLNotificationPtr& notify, bool should_log = true) = 0;  };  class LLSystemNotificationHandler : public LLNotificationHandler @@ -136,7 +136,7 @@ class LLIMHandler : public LLCommunicationNotificationHandler  public:  	LLIMHandler();  	virtual ~LLIMHandler(); -	bool processNotification(const LLNotificationPtr& p); +	bool processNotification(const LLNotificationPtr& p, bool should_log = true);  protected:  	virtual void initChannel(); @@ -152,7 +152,7 @@ public:  	LLTipHandler();  	virtual ~LLTipHandler(); -	virtual bool processNotification(const LLNotificationPtr& p); +	virtual bool processNotification(const LLNotificationPtr& p, bool should_log = true);  protected:  	virtual void initChannel(); @@ -170,7 +170,7 @@ public:  	virtual void onDelete(LLNotificationPtr p);  	virtual void onChange(LLNotificationPtr p); -	virtual bool processNotification(const LLNotificationPtr& p); +	virtual bool processNotification(const LLNotificationPtr& p, bool should_log = true);  	virtual void addToastWithNotification(const LLNotificationPtr& p);  protected: @@ -188,7 +188,7 @@ public:  	LLGroupHandler();  	virtual ~LLGroupHandler(); -	virtual bool processNotification(const LLNotificationPtr& p); +	virtual bool processNotification(const LLNotificationPtr& p, bool should_log = true);  protected:  	virtual void initChannel(); @@ -204,7 +204,7 @@ public:  	virtual ~LLAlertHandler();  	virtual void onChange(LLNotificationPtr p); -	virtual bool processNotification(const LLNotificationPtr& p); +	virtual bool processNotification(const LLNotificationPtr& p, bool should_log = true);  protected:  	virtual void initChannel(); @@ -220,7 +220,7 @@ public:  	virtual ~LLViewerAlertHandler() {};  	virtual void onDelete(LLNotificationPtr p) {}; -	virtual bool processNotification(const LLNotificationPtr& p); +	virtual bool processNotification(const LLNotificationPtr& p, bool should_log = true);  protected:  	virtual void initChannel() {}; @@ -238,7 +238,7 @@ public:  	virtual void onChange(LLNotificationPtr p);  	virtual void onDelete(LLNotificationPtr notification); -	virtual bool processNotification(const LLNotificationPtr& p); +	virtual bool processNotification(const LLNotificationPtr& p, bool should_log = true);  protected:  	virtual void initChannel(); @@ -256,7 +256,7 @@ public:  	virtual void onAdd(LLNotificationPtr p);  	virtual void onLoad(LLNotificationPtr p);  	virtual void onDelete(LLNotificationPtr p); -	virtual bool processNotification(const LLNotificationPtr& p); +	virtual bool processNotification(const LLNotificationPtr& p, bool should_log = true);  protected:  	virtual void initChannel() {}; @@ -271,7 +271,7 @@ public:  	LLBrowserNotification();  	virtual ~LLBrowserNotification() {} -	virtual bool processNotification(const LLNotificationPtr& p); +	virtual bool processNotification(const LLNotificationPtr& p, bool should_log = true);  protected:  	virtual void initChannel() {}; diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index f1226c53ff..44ebc5ed47 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -53,7 +53,7 @@ void LLHintHandler::onDelete(LLNotificationPtr p)  	LLHints::getInstance()->hide(p);  } -bool LLHintHandler::processNotification(const LLNotificationPtr& p) +bool LLHintHandler::processNotification(const LLNotificationPtr& p, bool should_log)  {  	return false;  } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index d9359d20cf..3f22467544 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -68,7 +68,7 @@ void LLOfferHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) +bool LLOfferHandler::processNotification(const LLNotificationPtr& notification, bool should_log)  {  	if(mChannel.isDead())  	{ diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index d896c409d7..bb39d8f362 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -93,7 +93,7 @@ void LLScriptHandler::addToastWithNotification(const LLNotificationPtr& notifica  }  //-------------------------------------------------------------------------- -bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) +bool LLScriptHandler::processNotification(const LLNotificationPtr& notification, bool should_log)  {  	if(mChannel.isDead())  	{ @@ -106,7 +106,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)  		initChannel();  	} -	if (notification->canLogToIM()) +	if (should_log && notification->canLogToIM())  	{  		LLHandlerUtil::logToIMP2P(notification);  	} diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index a6ef130cd0..91f93067de 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -66,7 +66,7 @@ void LLTipHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLTipHandler::processNotification(const LLNotificationPtr& notification) +bool LLTipHandler::processNotification(const LLNotificationPtr& notification, bool should_log)  {  	if(mChannel.isDead())  	{ diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 1f7bfbbf8a..4febb72c6c 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -61,6 +61,8 @@ static LLPanelInjector<LLOutfitGallery> t_outfit_gallery("outfit_gallery");  #define MAX_OUTFIT_PHOTO_WIDTH 256  #define MAX_OUTFIT_PHOTO_HEIGHT 256 +const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; +  LLOutfitGallery::LLOutfitGallery(const LLOutfitGallery::Params& p)      : LLOutfitListBase(),        mTexturesObserver(NULL), @@ -95,7 +97,7 @@ LLOutfitGallery::Params::Params()        item_width("item_width", 150),        item_height("item_height", 175),        item_horizontal_gap("item_horizontal_gap", 16), -      items_in_row("items_in_row", 3), +      items_in_row("items_in_row", GALLERY_ITEMS_PER_ROW_MIN),        row_panel_width_factor("row_panel_width_factor", 166),        gallery_width_factor("gallery_width_factor", 163)  { @@ -153,7 +155,7 @@ void LLOutfitGallery::updateRowsIfNeeded()      {          reArrangeRows(1);      } -    else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > 3) +    else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > GALLERY_ITEMS_PER_ROW_MIN)      {          reArrangeRows(-1);      } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index c63d04cd55..ab32ea3956 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -305,8 +305,11 @@ BOOL LLPanelGroupNotices::postBuild()  void LLPanelGroupNotices::activate()  { -	if(mNoticesList) -		mNoticesList->deleteAllItems(); +    if (mNoticesList) +    { +        mNoticesList->deleteAllItems(); +        mKnownNoticeIds.clear(); +    }  	mPrevSelectedNotice = LLUUID(); @@ -413,6 +416,7 @@ void LLPanelGroupNotices::onClickSendMessage(void* data)  	row["columns"][4]["value"] = llformat( "%u", timestamp);  	self->mNoticesList->addElement(row, ADD_BOTTOM); +	self->mKnownNoticeIds.insert(id);  	self->mCreateMessage->clear();  	self->mCreateSubject->clear(); @@ -443,27 +447,13 @@ void LLPanelGroupNotices::onClickNewMessage(void* data)  void LLPanelGroupNotices::refreshNotices()  {  	onClickRefreshNotices(this); -	/* -	LL_DEBUGS() << "LLPanelGroupNotices::onClickGetPastNotices" << LL_ENDL; -	 -	mNoticesList->deleteAllItems(); - -	LLMessageSystem* msg = gMessageSystem; -	msg->newMessage("GroupNoticesListRequest"); -	msg->nextBlock("AgentData"); -	msg->addUUID("AgentID",gAgent.getID()); -	msg->addUUID("SessionID",gAgent.getSessionID()); -	msg->nextBlock("Data"); -	msg->addUUID("GroupID",self->mGroupID); -	gAgent.sendReliableMessage(); -	*/ -	  }  void LLPanelGroupNotices::clearNoticeList()  {  	mPrevSelectedNotice = mNoticesList->getStringUUIDSelectedItem();  	mNoticesList->deleteAllItems(); +	mKnownNoticeIds.clear();  }  void LLPanelGroupNotices::onClickRefreshNotices(void* data) @@ -541,13 +531,14 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)  			return;  		} -		//with some network delays we can receive notice list more then once... -		//so add only unique notices -		S32 pos = mNoticesList->getItemIndex(id); +        // Due to some network delays we can receive notice list more than once... +        // So add only unique notices +        if (mKnownNoticeIds.find(id) != mKnownNoticeIds.end()) +        { +            // If items with this ID already in the list - skip it +            continue; +        } -		if(pos!=-1)//if items with this ID already in the list - skip it -			continue; -			  		msg->getString("Data","Subject",subj,i);  		msg->getString("Data","FromName",name,i);  		msg->getBOOL("Data","HasAttachment",has_attachment,i); @@ -582,6 +573,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)  		row["columns"][4]["value"] = llformat( "%u", timestamp);  		mNoticesList->addElement(row, ADD_BOTTOM); +		mKnownNoticeIds.insert(id);  	}  	mNoticesList->setNeedsSort(save_sort); diff --git a/indra/newview/llpanelgroupnotices.h b/indra/newview/llpanelgroupnotices.h index 46c8c241c6..55319cb9ae 100644 --- a/indra/newview/llpanelgroupnotices.h +++ b/indra/newview/llpanelgroupnotices.h @@ -110,6 +110,7 @@ private:  	LLIconCtrl		 *mViewInventoryIcon;  	LLScrollListCtrl *mNoticesList; +    std::set<LLUUID>  mKnownNoticeIds; // Dupplicate avoidance, to avoid searching and inserting dupplciates into mNoticesList  	std::string		mNoNoticesStr; diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 880323ce16..834e664723 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -371,6 +371,11 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)  	setFocus(TRUE);  } +void LLPanelLandmarkInfo::setCanEdit(BOOL enabled) +{ +    getChild<LLButton>("edit_btn")->setEnabled(enabled); +} +  const std::string& LLPanelLandmarkInfo::getLandmarkTitle() const  {  	return mLandmarkTitleEditor->getText(); diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h index f727f286b5..46e2a1935b 100644 --- a/indra/newview/llpanellandmarkinfo.h +++ b/indra/newview/llpanellandmarkinfo.h @@ -56,6 +56,7 @@ public:  	void displayItemInfo(const LLInventoryItem* pItem);  	void toggleLandmarkEditMode(BOOL enabled); +	void setCanEdit(BOOL enabled);  	const std::string& getLandmarkTitle() const;  	const std::string getLandmarkNotes() const; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index e698a61fef..ce17da3076 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -438,8 +438,14 @@ void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list  	LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder());  	if (root_folder)  	{ -		root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle()); -		root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle()); +        if (mGearFolderMenu) +        { +            root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle()); +        } +        if (mGearLandmarkMenu) +        { +            root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle()); +        }  		root_folder->setParentLandmarksPanel(this);  	} @@ -462,13 +468,23 @@ void LLLandmarksPanel::initListCommandsHandlers()  	mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_sorting.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());  	mAddMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	mGearLandmarkMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2)); -	mGearFolderMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2)); +    if (mGearLandmarkMenu) +    { +        mGearLandmarkMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2)); +        // show menus even if all items are disabled +        mGearLandmarkMenu->setAlwaysShowMenu(TRUE); +    } // Else corrupted files? + +    if (mGearFolderMenu) +    { +        mGearFolderMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2)); +        mGearFolderMenu->setAlwaysShowMenu(TRUE); +    } -	// show menus even if all items are disabled -	mGearLandmarkMenu->setAlwaysShowMenu(TRUE); -	mGearFolderMenu->setAlwaysShowMenu(TRUE); -	mAddMenu->setAlwaysShowMenu(TRUE); +    if (mAddMenu) +    { +        mAddMenu->setAlwaysShowMenu(TRUE); +    }  }  void LLLandmarksPanel::updateMenuVisibility(LLUICtrl* menu) @@ -1054,7 +1070,10 @@ void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark)  		LLFloaterReg::showInstance("world_map", "center");  	} -	mGearLandmarkMenu->setItemEnabled("show_on_map", TRUE); +    if (mGearLandmarkMenu) +    { +        mGearLandmarkMenu->setItemEnabled("show_on_map", TRUE); +    }  }  void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark, diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 1a1792fb60..89256b40c4 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -162,7 +162,6 @@ BOOL LLPanelMainInventory::postBuild()  		recent_items_panel->setSinceLogoff(TRUE);  		recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);  		recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -		recent_items_panel->setFilterLinks(LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS);  		LLInventoryFilter& recent_filter = recent_items_panel->getFilter();  		recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY));  		recent_filter.setEmptyLookupMessage("InventoryNoMatchingRecentItems"); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index ecadc9443b..0d987df6ca 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1589,6 +1589,7 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  							   child_categories[i]->second );  		delete child_categories[i];  	} +    folder->setChildrenInited(true);  }  void LLPanelObjectInventory::refresh() diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 9c67ec40fe..69f181e1b3 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -469,10 +469,15 @@ void LLPanelPlaces::onOpen(const LLSD& key)  			{  				mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK); -				LLInventoryItem* item = gInventory.getItem(key["id"].asUUID()); +				LLUUID id = key["id"].asUUID(); +				LLInventoryItem* item = gInventory.getItem(id);  				if (!item)  					return; +                BOOL is_editable = gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()) +                                   && item->getPermissions().allowModifyBy(gAgent.getID()); +                mLandmarkInfo->setCanEdit(is_editable); +  				setItem(item);  			}  			else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE) diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 20cf4df56b..9bc77393dc 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -146,7 +146,7 @@ void LLPersistentNotificationStorage::loadNotifications()  		LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"]));  		notification->setResponseFunctor(responder); -		instance.add(notification); +		instance.load(notification);  		// hide script floaters so they don't confuse the user and don't overlap startup toast  		LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index b41aa2be1a..9ac15d1639 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -104,7 +104,7 @@ public:  	// llview  	/*virtual*/ void draw(); -	void refreshFromItem(); +	virtual void refreshFromItem();  	// We can't modify Item or description in preview if either in-world Object  	// or Item  itself is unmodifiable diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index 12ac9e6fc5..7f01438425 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -35,11 +35,13 @@  #include "llkeyframemotion.h"  #include "llfilepicker.h"  #include "lllineeditor.h" +#include "lltrans.h"  #include "lluictrlfactory.h"  #include "lluictrlfactory.h"  #include "lldatapacker.h"  extern LLAgent gAgent; +const S32 ADVANCED_VPAD = 3;  LLPreviewAnim::LLPreviewAnim(const LLSD& key)  	: LLPreview( key ) @@ -50,20 +52,19 @@ LLPreviewAnim::LLPreviewAnim(const LLSD& key)  // virtual  BOOL LLPreviewAnim::postBuild()  { -	const LLInventoryItem* item = getItem(); -	if(item) -	{ -		gAgentAvatarp->createMotion(item->getAssetUUID()); // preload the animation -		getChild<LLUICtrl>("desc")->setValue(item->getDescription()); -	} -  	childSetCommitCallback("desc", LLPreview::onText, this);  	getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); +	getChild<LLTextBox>("adv_trigger")->setClickedCallback(boost::bind(&LLPreviewAnim::showAdvanced, this)); +	pAdvancedStatsTextBox = getChild<LLTextBox>("AdvancedStats"); + +    // Assume that advanced stats start visible (for XUI preview tool's purposes) +    pAdvancedStatsTextBox->setVisible(FALSE); +    LLRect rect = getRect(); +    reshape(rect.getWidth(), rect.getHeight() - pAdvancedStatsTextBox->getRect().getHeight() - ADVANCED_VPAD, FALSE);  	return LLPreview::postBuild();  } -// static  // llinventorybridge also calls into here  void LLPreviewAnim::play(const LLSD& param)  { @@ -161,14 +162,28 @@ void LLPreviewAnim::draw()  }  // virtual +void LLPreviewAnim::refreshFromItem() +{ +    const LLInventoryItem* item = getItem(); +    if (!item) +    { +        return; +    } + +    // Preload motion +    gAgentAvatarp->createMotion(item->getAssetUUID());   + +    LLPreview::refreshFromItem(); +} +  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); +	getChild<LLUICtrl>("Inworld")->setEnabled(TRUE); +	getChild<LLUICtrl>("Locally")->setEnabled(TRUE);  }  // virtual @@ -182,3 +197,41 @@ void LLPreviewAnim::onClose(bool app_quitting)  		gAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP);  	}  } + +void LLPreviewAnim::showAdvanced() +{ +    BOOL was_visible =  pAdvancedStatsTextBox->getVisible(); + +    if (was_visible) +    { +        pAdvancedStatsTextBox->setVisible(FALSE); +        LLRect rect = getRect(); +        reshape(rect.getWidth(), rect.getHeight() - pAdvancedStatsTextBox->getRect().getHeight() - ADVANCED_VPAD, FALSE); +    } +    else +    { +        pAdvancedStatsTextBox->setVisible(TRUE); +        LLRect rect = getRect(); +        reshape(rect.getWidth(), rect.getHeight() + pAdvancedStatsTextBox->getRect().getHeight() + ADVANCED_VPAD, FALSE); + +        LLMotion *motion = NULL; +        const LLInventoryItem* item = getItem(); +        if (item) +        { +            // if motion exists, will return existing one. +            // Needed because viewer can purge motions +            motion = gAgentAvatarp->createMotion(item->getAssetUUID()); +        } + +        // set text +        if (motion) +        { +            pAdvancedStatsTextBox->setTextArg("[PRIORITY]", llformat("%d", motion->getPriority())); +            pAdvancedStatsTextBox->setTextArg("[DURATION]", llformat("%.2f", motion->getDuration())); +            pAdvancedStatsTextBox->setTextArg("[EASE_IN]", llformat("%.2f", motion->getEaseInDuration())); +            pAdvancedStatsTextBox->setTextArg("[EASE_OUT]", llformat("%.2f", motion->getEaseOutDuration())); +            pAdvancedStatsTextBox->setTextArg("[IS_LOOP]", (motion->getLoop() ? LLTrans::getString("PermYes") : LLTrans::getString("PermNo"))); +            pAdvancedStatsTextBox->setTextArg("[NUM_JOINTS]", llformat("%d", motion->getNumJointMotions())); +        } +    } +} diff --git a/indra/newview/llpreviewanim.h b/indra/newview/llpreviewanim.h index 8eaed6ca1f..9f4ad4fa69 100644 --- a/indra/newview/llpreviewanim.h +++ b/indra/newview/llpreviewanim.h @@ -30,21 +30,28 @@  #include "llpreview.h"  #include "llcharacter.h" +class LLMotion; +class LLTextBox; +  class LLPreviewAnim : public LLPreview  {  public:  	LLPreviewAnim(const LLSD& key); -	/*virtual*/	BOOL postBuild(); -	/*virtual*/ void onClose(bool app_quitting); -	void draw(); -	void cleanup(); +	BOOL postBuild() override; +	void onClose(bool app_quitting) override; +	void draw() override; +	void refreshFromItem() override; + +	void cleanup(); // cleanup 'playing' state  	void play(const LLSD& param); -	 +	void showAdvanced(); +  protected: -	LLUUID	mItemID; +	LLUUID	mItemID; // Not an item id, but a playing asset id  	bool	mDidStart; +	LLTextBox* pAdvancedStatsTextBox;  };  #endif  // LL_LLPREVIEWANIM_H diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b3d3e9e0da..82a165cb35 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1366,9 +1366,11 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &  			}  			break;  		case SELECT_TYPE_HUD: -		case SELECT_TYPE_WORLD:  			mGridScale = LLVector3(1.f, 1.f, 1.f) * llmin(gSavedSettings.getF32("GridResolution"), 0.5f);  			break; +		case SELECT_TYPE_WORLD: +			mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); +			break;  		}  	}  	llassert(mGridOrigin.isFinite()); diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp index 4b36822e9a..74844a80e8 100644 --- a/indra/newview/llsetkeybinddialog.cpp +++ b/indra/newview/llsetkeybinddialog.cpp @@ -96,7 +96,7 @@ BOOL LLSetKeyBindDialog::postBuild()      getChild<LLUICtrl>("Cancel")->setFocus(TRUE);      pCheckBox = getChild<LLCheckBoxCtrl>("apply_all"); -    pDesription = getChild<LLTextBase>("descritption"); +    pDescription = getChild<LLTextBase>("description");      gFocusMgr.setKeystrokesOnly(TRUE); @@ -160,8 +160,8 @@ void LLSetKeyBindDialog::setParent(LLKeyBindResponderInterface* parent, LLView*          }          input += getString("keyboard");      } -    pDesription->setText(getString("basic_description")); -    pDesription->setTextArg("[INPUT]", input); +    pDescription->setText(getString("basic_description")); +    pDescription->setTextArg("[INPUT]", input);  }  // static @@ -257,8 +257,8 @@ bool LLSetKeyBindDialog::recordAndHandleKey(KEY key, MASK mask, BOOL down)      if (LLKeyConflictHandler::isReservedByMenu(key, mask))      { -        pDesription->setText(getString("reserved_by_menu")); -        pDesription->setTextArg("[KEYSTR]", LLKeyboard::stringFromAccelerator(mask,key)); +        pDescription->setText(getString("reserved_by_menu")); +        pDescription->setTextArg("[KEYSTR]", LLKeyboard::stringFromAccelerator(mask,key));          mLastMaskKey = 0;          return true;      } diff --git a/indra/newview/llsetkeybinddialog.h b/indra/newview/llsetkeybinddialog.h index 24dfa1dbfd..18e2601723 100644 --- a/indra/newview/llsetkeybinddialog.h +++ b/indra/newview/llsetkeybinddialog.h @@ -85,7 +85,7 @@ private:      void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes);      LLKeyBindResponderInterface *pParent;      LLCheckBoxCtrl *pCheckBox; -    LLTextBase *pDesription; +    LLTextBase *pDescription;      U32 mKeyFilterMask;      Updater *pUpdater; diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index ea7e649792..a5dcdc41ed 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -653,7 +653,12 @@ bool LLSidepanelInventory::canWearSelected()  LLInventoryItem *LLSidepanelInventory::getSelectedItem()  { -	LLFolderViewItem* current_item = mPanelMainInventory->getActivePanel()->getRootFolder()->getCurSelectedItem(); +    LLFolderView* root = mPanelMainInventory->getActivePanel()->getRootFolder(); +    if (!root) +    { +        return NULL; +    } +	LLFolderViewItem* current_item = root->getCurSelectedItem();  	if (!current_item)  	{ diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index da8d5152b4..94bafcb612 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1174,6 +1174,10 @@ bool idle_startup()  						}  					} +                    else if (reason_response == "BadType") +                    { +                        LLNotificationsUtil::add("LoginFailedToParse", LLSD(), LLSD(), login_alert_done); +                    }  					else if (!message.empty())  					{  						// This wasn't a certificate error, so throw up the normal @@ -1835,6 +1839,17 @@ bool idle_startup()  		// This method MUST be called before gInventory.findCategoryUUIDForType because of   		// gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.  		gInventory.buildParentChildMap(); + +		// If buildParentChildMap succeeded, inventory will now be in +		// a usable state and gInventory.isInventoryUsable() will be +		// true. + +		// if inventory is unusable, show warning. +		if (!gInventory.isInventoryUsable()) +		{ +			LLNotificationsUtil::add("InventoryUnusable"); +		} +		  		gInventory.createCommonSystemCategories();  		// It's debatable whether this flag is a good idea - sets all @@ -1867,6 +1882,7 @@ bool idle_startup()  		display_startup();  		LLStartUp::setStartupState( STATE_MISC );  		display_startup(); +  		return FALSE;  	} @@ -2156,7 +2172,10 @@ bool idle_startup()  		if (gAgent.isOutfitChosen() && (wearables_time > max_wearables_time))  		{ -			LLNotificationsUtil::add("ClothingLoading"); +			if (gInventory.isInventoryUsable()) +			{ +				LLNotificationsUtil::add("ClothingLoading"); +			}			  			record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time);  			LLStartUp::setStartupState( STATE_CLEANUP );  		} diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 73a25397fd..0edaf40c66 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -70,8 +70,12 @@ LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > LLTextureFetch::sCacheH  LLTrace::SampleStatHandle<F32Seconds> LLTextureFetch::sCacheReadLatency("texture_cache_read_latency");  LLTrace::SampleStatHandle<F32Seconds> LLTextureFetch::sTexDecodeLatency("texture_decode_latency"); +LLTrace::SampleStatHandle<F32Seconds> LLTextureFetch::sCacheWriteLatency("texture_write_latency");  LLTrace::SampleStatHandle<F32Seconds> LLTextureFetch::sTexFetchLatency("texture_fetch_latency"); +LLTextureFetchTester* LLTextureFetch::sTesterp = NULL ; +const std::string sTesterName("TextureFetchTester"); +  //////////////////////////////////////////////////////////////////////////////  //  // Introduction @@ -441,6 +445,29 @@ public:  	// Threads:  Ttf  	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); +	enum e_state // mState +	{ +		// *NOTE:  Do not change the order/value of state variables, some code +		// depends upon specific ordering/adjacency. + +		// NOTE: Affects LLTextureBar::draw in lltextureview.cpp (debug hack) +		INVALID = 0, +		INIT, +		LOAD_FROM_TEXTURE_CACHE, +		CACHE_POST, +		LOAD_FROM_NETWORK, +		LOAD_FROM_SIMULATOR, +		WAIT_HTTP_RESOURCE,				// Waiting for HTTP resources +		WAIT_HTTP_RESOURCE2,			// Waiting for HTTP resources +		SEND_HTTP_REQ,					// Commit to sending as HTTP +		WAIT_HTTP_REQ,					// Request sent, wait for completion +		DECODE_IMAGE, +		DECODE_IMAGE_UPDATE, +		WRITE_TO_CACHE, +		WAIT_ON_WRITE, +		DONE +	}; +  protected:  	LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type,  						 const std::string& url, const LLUUID& id, const LLHost& host, @@ -520,28 +547,6 @@ private:  		}  private: -	enum e_state // mState -	{ -		// *NOTE:  Do not change the order/value of state variables, some code -		// depends upon specific ordering/adjacency. -		 -		// NOTE: Affects LLTextureBar::draw in lltextureview.cpp (debug hack) -		INVALID = 0, -		INIT, -		LOAD_FROM_TEXTURE_CACHE, -		CACHE_POST, -		LOAD_FROM_NETWORK, -		LOAD_FROM_SIMULATOR, -		WAIT_HTTP_RESOURCE,				// Waiting for HTTP resources -		WAIT_HTTP_RESOURCE2,			// Waiting for HTTP resources -		SEND_HTTP_REQ,					// Commit to sending as HTTP -		WAIT_HTTP_REQ,					// Request sent, wait for completion -		DECODE_IMAGE, -		DECODE_IMAGE_UPDATE, -		WRITE_TO_CACHE, -		WAIT_ON_WRITE, -		DONE -	};  	enum e_request_state // mSentRequest  	{  		UNSENT = 0, @@ -554,7 +559,7 @@ private:  		CAN_WRITE = 1,  		SHOULD_WRITE = 2  	}; -	static const char* sStateDescs[]; +  	e_state mState;  	void setState(e_state new_state); @@ -582,10 +587,15 @@ private:  	LLFrameTimer mFetchDeltaTimer;  	LLTimer mCacheReadTimer;      LLTimer mDecodeTimer; +	LLTimer mCacheWriteTimer;      LLTimer mFetchTimer; +	LLTimer mStateTimer;  	F32 mCacheReadTime; // time for cache read only      F32 mDecodeTime;    // time for decode only +	F32 mCacheWriteTime;      F32 mFetchTime;     // total time from req to finished fetch +	std::map<S32, F32> mStateTimersMap; +	F32 mSkippedStatesTime;  	LLTextureCache::handle_t    mCacheReadHandle,  								mCacheWriteHandle;  	S32                         mRequestedSize, @@ -869,8 +879,7 @@ bool truncate_viewer_metrics(int max_regions, LLSD & metrics);  ////////////////////////////////////////////////////////////////////////////// -//static -const char* LLTextureFetchWorker::sStateDescs[] = { +const char* sStateDescs[] = {  	"INVALID",  	"INIT",  	"LOAD_FROM_TEXTURE_CACHE", @@ -888,6 +897,9 @@ const char* LLTextureFetchWorker::sStateDescs[] = {  	"DONE"  }; +const std::set<S32> LOGGED_STATES = { LLTextureFetchWorker::LOAD_FROM_TEXTURE_CACHE, LLTextureFetchWorker::LOAD_FROM_NETWORK, LLTextureFetchWorker::LOAD_FROM_SIMULATOR,  +										LLTextureFetchWorker::WAIT_HTTP_REQ, LLTextureFetchWorker::DECODE_IMAGE_UPDATE, LLTextureFetchWorker::WAIT_ON_WRITE }; +  // static  volatile bool LLTextureFetch::svMetricsDataBreak(true);	// Start with a data break @@ -919,6 +931,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,  	  mLoadedDiscard(-1),  	  mDecodedDiscard(-1),  	  mCacheReadTime(0.f), +	  mCacheWriteTime(0.f),  	  mDecodeTime(0.f),        mFetchTime(0.f),  	  mCacheReadHandle(LLTextureCache::nullHandle()), @@ -927,6 +940,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,  	  mRequestedOffset(0),  	  mDesiredSize(TEXTURE_CACHE_ENTRY_SIZE),  	  mFileSize(0), +	  mSkippedStatesTime(0),  	  mCachedSize(0),  	  mLoaded(FALSE),  	  mSentRequest(UNSENT), @@ -1192,6 +1206,13 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == INIT)  	{		 +		mStateTimer.reset(); +		mFetchTimer.reset(); +		for(auto i : LOGGED_STATES)  +		{ +			mStateTimersMap[i] = 0; +		} +		mSkippedStatesTime = 0;  		mRawImage = NULL ;  		mRequestedDiscard = -1;  		mLoadedDiscard = -1; @@ -1249,9 +1270,10 @@ bool LLTextureFetchWorker::doWork(S32 param)  				++mCacheReadCount;  				std::string filename = mUrl.substr(7, std::string::npos);  				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); +				mCacheReadTimer.reset();    				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,  																		  offset, size, responder); -                mCacheReadTimer.reset();                 +                			}  			else if ((mUrl.empty() || mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache())  			{ @@ -1259,9 +1281,9 @@ bool LLTextureFetchWorker::doWork(S32 param)  				++mCacheReadCount;  				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); -				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, -																		  offset, size, responder);  				mCacheReadTimer.reset(); +				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, +																		  offset, size, responder);;  			}  			else if(!mUrl.empty() && mCanUseHTTP)  			{ @@ -1283,6 +1305,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  				mCacheReadHandle = LLTextureCache::nullHandle();  				setState(CACHE_POST);                  add(LLTextureFetch::sCacheHit, 1.0); +				mCacheReadTime = mCacheReadTimer.getElapsedTimeF32();  				// fall through  			}  			else @@ -1896,7 +1919,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  			LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: mLoadedDiscard < 0" << LL_ENDL;  			return true;  		} - +		mDecodeTimer.reset();  		mRawImage = NULL;  		mAuxImage = NULL;  		llassert_always(mFormattedImage.notNull()); @@ -1990,6 +2013,7 @@ bool LLTextureFetchWorker::doWork(S32 param)          // be protected by work mutex and won't be safe to use here nor in cache worker.          // So make sure users of getRequestFinished() does not attempt to modify image while          // fetcher is working +		mCacheWriteTimer.reset();  		mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority,  																  mFormattedImage->getData(), datasize,  																  mFileSize, mRawImage, mDecodedDiscard, responder); @@ -2000,6 +2024,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	{  		if (writeToCacheComplete())  		{ +			mCacheWriteTime = mCacheWriteTimer.getElapsedTimeF32();  			setState(DONE);  			// fall through  		} @@ -2508,7 +2533,6 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag  	mDecoded = TRUE;  // 	LL_INFOS(LOG_TXT) << mID << " : DECODE COMPLETE " << LL_ENDL;  	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); -	mCacheReadTime = mCacheReadTimer.getElapsedTimeF32();  }																		// -Mw  ////////////////////////////////////////////////////////////////////////////// @@ -2633,6 +2657,17 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image  		}  		mOriginFetchSource = mFetchSource;  	} + +	// If that test log has ben requested but not yet created, create it +	if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) +	{ +		sTesterp = new LLTextureFetchTester() ; +		if (!sTesterp->isValid()) +		{ +			delete sTesterp; +			sTesterp = NULL; +		} +	}  }  LLTextureFetch::~LLTextureFetch() @@ -2974,20 +3009,51 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,  		}  		else if (worker->checkWork())  		{ +			F32 decode_time; +			F32 fetch_time; +			F32 cache_read_time; +			F32 cache_write_time; +			S32 file_size; +			std::map<S32, F32> logged_state_timers; +			F32 skipped_states_time;  			worker->lockWorkMutex();									// +Mw  			last_http_get_status = worker->mGetStatus;  			discard_level = worker->mDecodedDiscard;  			raw = worker->mRawImage;  			aux = worker->mAuxImage; -			sample(sTexDecodeLatency, worker->mDecodeTime); -            sample(sTexFetchLatency, worker->mFetchTime); -            sample(sCacheReadLatency, worker->mCacheReadTime); + +			decode_time = worker->mDecodeTime; +			fetch_time = worker->mFetchTime; +			cache_read_time = worker->mCacheReadTime; +			cache_write_time = worker->mCacheWriteTime; +			file_size = worker->mFileSize;              worker->mCacheReadTimer.reset();              worker->mDecodeTimer.reset(); +			worker->mCacheWriteTimer.reset();              worker->mFetchTimer.reset(); +			logged_state_timers = worker->mStateTimersMap; +			skipped_states_time = worker->mSkippedStatesTime; +			worker->mStateTimer.reset();  			res = true;  			LL_DEBUGS(LOG_TXT) << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL;  			worker->unlockWorkMutex();									// -Mw +			 +			sample(sTexDecodeLatency, decode_time); +			sample(sTexFetchLatency, fetch_time); +			sample(sCacheReadLatency, cache_read_time); +			sample(sCacheWriteLatency, cache_write_time); +			 +			static LLCachedControl<F32> min_time_to_log(gSavedSettings, "TextureFetchMinTimeToLog", 2.f); +			if (fetch_time > min_time_to_log) +			{ +				//LL_INFOS() << "fetch_time: " << fetch_time << " cache_read_time: " << cache_read_time << " decode_time: " << decode_time << " cache_write_time: " << cache_write_time << LL_ENDL; + +				LLTextureFetchTester* tester = (LLTextureFetchTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); +				if (tester) +				{ +					tester->updateStats(logged_state_timers, fetch_time, skipped_states_time, file_size) ; +				} +			}  		}  		else  		{ @@ -3472,6 +3538,21 @@ void LLTextureFetchWorker::setState(e_state new_state)  //		LL_INFOS(LOG_TXT) << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << LL_ENDL;  	} +	 +	F32 d_time = mStateTimer.getElapsedTimeF32(); +	if (d_time >= 0.0001F) +	{ +		if (LOGGED_STATES.count(mState)) +		{ +			mStateTimersMap[mState] = d_time; +		} +		else +		{ +			mSkippedStatesTime += d_time; +		} +	} +	 +	mStateTimer.reset();  	mState = new_state;  } @@ -3687,7 +3768,7 @@ void LLTextureFetch::dump()  		LLTextureFetchWorker* worker = (LLTextureFetchWorker*)wreq->getWorkerClass();  		LL_INFOS(LOG_TXT) << " ID: " << worker->mID  						  << " PRI: " << llformat("0x%08x",wreq->getPriority()) -						  << " STATE: " << worker->sStateDescs[worker->mState] +						  << " STATE: " << sStateDescs[worker->mState]  						  << LL_ENDL;  	} @@ -5129,4 +5210,40 @@ void LLTextureFetchDebugger::callbackHTTP(FetchEntry & fetch, LLCore::HttpRespon  //End LLTextureFetchDebugger  /////////////////////////////////////////////////////////////////////////////////////////// +LLTextureFetchTester::LLTextureFetchTester() : LLMetricPerformanceTesterBasic(sTesterName)  +{ +	mTextureFetchTime = 0; +	mSkippedStatesTime = 0; +	mFileSize = 0; +} + +LLTextureFetchTester::~LLTextureFetchTester() +{ +	outputTestResults(); +	LLTextureFetch::sTesterp = NULL; +} + +//virtual  +void LLTextureFetchTester::outputTestRecord(LLSD *sd)  +{	 +	std::string currentLabel = getCurrentLabelName(); + +	(*sd)[currentLabel]["Texture Fetch Time"]	= (LLSD::Real)mTextureFetchTime; +	(*sd)[currentLabel]["File Size"]			= (LLSD::Integer)mFileSize; +	(*sd)[currentLabel]["Skipped States Time"]	= (LLSD::String)llformat("%.6f", mSkippedStatesTime); + +	for(auto i : LOGGED_STATES)  +	{ +		(*sd)[currentLabel][sStateDescs[i]] = mStateTimersMap[i]; +	} +} + +void LLTextureFetchTester::updateStats(const std::map<S32, F32> state_timers, const F32 fetch_time, const F32 skipped_states_time, const S32 file_size) +{ +	mTextureFetchTime = fetch_time; +	mStateTimersMap = state_timers; +	mFileSize = file_size; +	mSkippedStatesTime = skipped_states_time; +	outputTestResults(); +} diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 2aa194e141..bf6732963f 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -50,6 +50,7 @@ class LLHost;  class LLViewerAssetStats;  class LLTextureFetchDebugger;  class LLTextureCache; +class LLTextureFetchTester;  // Interface class @@ -312,6 +313,7 @@ public:      static LLTrace::CountStatHandle<F64>        sCacheAttempt;      static LLTrace::SampleStatHandle<F32Seconds> sCacheReadLatency;      static LLTrace::SampleStatHandle<F32Seconds> sTexDecodeLatency; +	static LLTrace::SampleStatHandle<F32Seconds> sCacheWriteLatency;      static LLTrace::SampleStatHandle<F32Seconds> sTexFetchLatency;      static LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > sCacheHitRate; @@ -403,6 +405,9 @@ public:  		FROM_HTTP_ONLY,  		INVALID_SOURCE  	}; + +	static LLTextureFetchTester* sTesterp; +  private:  	//debug use  	LLTextureFetchDebugger* mFetchDebugger; @@ -635,5 +640,26 @@ private:  public:  	static bool isEnabled() {return sDebuggerEnabled;}  }; + + +class LLTextureFetchTester : public LLMetricPerformanceTesterBasic +{ +public: +	LLTextureFetchTester(); +	~LLTextureFetchTester(); + +	void updateStats(const std::map<S32, F32> states_timers, const F32 fetch_time, const F32 other_states_time, const S32 file_size); + +protected: +	/*virtual*/ void outputTestRecord(LLSD* sd); + +private: + +	F32 mTextureFetchTime; +	F32 mSkippedStatesTime; +	S32 mFileSize; + +	std::map<S32, F32> mStateTimersMap; +};  #endif // LL_LLTEXTUREFETCH_H diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index f9c327b46e..ba328f27c4 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -343,7 +343,9 @@ BOOL LLToolCompTranslate::handleDoubleClick(S32 x, S32 y, MASK mask)  	}  	// Nothing selected means the first mouse click was probably  	// bad, so try again. -	return FALSE; +	// This also consumes the event to prevent things like double-click +	// teleport from triggering. +	return handleMouseDown(x, y, mask);  } diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 54ff7d295e..b4736841d6 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -173,7 +173,9 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)  	mMouseButtonDown = true; -    return handleLeftClickPick(); +	// If nothing clickable is picked, needs to return +	// false for click-to-walk or click-to-teleport to work. +	return handleLeftClickPick();  }  // Spawn context menus on right mouse down so you can drag over and select @@ -791,7 +793,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)  			gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);  			LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL;  		} -		else if ((!object || !object->isAttachment() || object->getClickAction() != CLICK_ACTION_DISABLED) +		else if ((!object || object->getClickAction() != CLICK_ACTION_DISABLED)  				 && ((object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch()))  				 && (!object || !object->isAvatar()))  		{ diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 0f102411d5..6aa1273174 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -102,10 +102,11 @@ public:  /// LLViewerAssetStorage  ///---------------------------------------------------------------------------- +S32 LLViewerAssetStorage::sAssetCoroCount = 0; +  // Unused?  LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, const LLHost &upstream_host)      : LLAssetStorage(msg, xfer, upstream_host), -      mAssetCoroCount(0),        mCountRequests(0),        mCountStarted(0),        mCountCompleted(0), @@ -117,7 +118,6 @@ LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *  LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer)      : LLAssetStorage(msg, xfer), -      mAssetCoroCount(0),        mCountRequests(0),        mCountStarted(0),        mCountCompleted(0), @@ -477,8 +477,7 @@ void LLViewerAssetStorage::assetRequestCoro(      LLGetAssetCallback callback,      void *user_data)  { -    LLScopedIncrement coro_count_boost(mAssetCoroCount); -    mCountStarted++; +    LLScopedIncrement coro_count_boost(sAssetCoroCount); // static counter since corotine can outlive LLViewerAssetStorage      S32 result_code = LL_ERR_NOERR;      LLExtStat ext_status = LLExtStat::NONE; @@ -488,6 +487,9 @@ void LLViewerAssetStorage::assetRequestCoro(          LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: asset storage no longer exists" << LL_ENDL;          return;      } + +    mCountStarted++; +      if (!gAgent.getRegion())      {          LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; @@ -554,6 +556,18 @@ void LLViewerAssetStorage::assetRequestCoro(          result_code = LL_ERR_ASSET_REQUEST_FAILED;          ext_status = LLExtStat::NONE;      } +    else if (!result.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW)) +    { +        LL_DEBUGS("ViewerAsset") << "request failed, no data returned!" << LL_ENDL; +        result_code = LL_ERR_ASSET_REQUEST_FAILED; +        ext_status = LLExtStat::NONE; +    } +    else if (!result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].isBinary()) +    { +        LL_DEBUGS("ViewerAsset") << "request failed, invalid data format!" << LL_ENDL; +        result_code = LL_ERR_ASSET_REQUEST_FAILED; +        ext_status = LLExtStat::NONE; +    }      else      {          LL_DEBUGS("ViewerAsset") << "request succeeded, url " << url << LL_ENDL; @@ -613,7 +627,7 @@ std::string LLViewerAssetStorage::getAssetURL(const std::string& cap_url, const  void LLViewerAssetStorage::logAssetStorageInfo()  {      LLMemory::logMemoryInfo(true); -    LL_INFOS("AssetStorage") << "Active coros " << mAssetCoroCount << LL_ENDL; +    LL_INFOS("AssetStorage") << "Active coros " << sAssetCoroCount << LL_ENDL;      LL_INFOS("AssetStorage") << "mPendingDownloads size " << mPendingDownloads.size() << LL_ENDL;      LL_INFOS("AssetStorage") << "mCountStarted " << mCountStarted << LL_ENDL;      LL_INFOS("AssetStorage") << "mCountCompleted " << mCountCompleted << LL_ENDL; diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index af7fbb5fbf..0965a17ce1 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -122,12 +122,13 @@ protected:      wait_list_t mCoroWaitList;      std::string mViewerAssetUrl; -    S32 mAssetCoroCount;      S32 mCountRequests;      S32 mCountStarted;      S32 mCountCompleted;      S32 mCountSucceeded;      S64 mTotalBytesFetched; + +    static S32 sAssetCoroCount; // coroutine count, static since coroutines can outlive LLViewerAssetStorage  };  #endif diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index f97ba0930e..f810e5f4ef 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -83,6 +83,8 @@ void LLViewerAudio::registerIdleListener()  void LLViewerAudio::startInternetStreamWithAutoFade(const std::string &streamURI)  { +    LL_DEBUGS("AudioEngine") << "Start with outo fade: " << streamURI << LL_ENDL; +  	// Old and new stream are identical  	if (mNextStreamURI == streamURI)  	{ @@ -166,6 +168,7 @@ bool LLViewerAudio::onIdleUpdate()  			if (gAudiop)  			{  				// Clear URI +                LL_DEBUGS("AudioEngine") << "Done with audio fade" << LL_ENDL;  				gAudiop->startInternetStream(LLStringUtil::null);  				gAudiop->stopInternetStream();  			} @@ -176,6 +179,7 @@ bool LLViewerAudio::onIdleUpdate()  				if (gAudiop)  				{ +                    LL_DEBUGS("AudioEngine") << "Audio fade in: " << mNextStreamURI << LL_ENDL;  					LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();  					if(stream && stream->supportsAdjustableBufferSizes())  						stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize")); @@ -219,6 +223,7 @@ void LLViewerAudio::stopInternetStreamWithAutoFade()  	if (gAudiop)  	{ +        LL_DEBUGS("AudioEngine") << "Stop audio fade" << LL_ENDL;  		gAudiop->startInternetStream(LLStringUtil::null);  		gAudiop->stopInternetStream();  	} diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index 782c523d4f..3b4f898710 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -47,6 +47,7 @@ class LLViewerJoystick : public LLSingleton<LLViewerJoystick>  {  	LLSINGLETON(LLViewerJoystick);  	virtual ~LLViewerJoystick(); +    LOG_CLASS(LLViewerJoystick);  public:  	void init(bool autoenable); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 63f57e81cc..2bc0eeed92 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -78,41 +78,12 @@  #include <boost/bind.hpp>	// for SkinFolder listener  #include <boost/signals2.hpp> -class LLMediaFilePicker : public LLFilePickerThread // deletes itself when done -{ -public: -    LLMediaFilePicker(LLPluginClassMedia* plugin, LLFilePicker::ELoadFilter filter, bool get_multiple) -        : LLFilePickerThread(filter, get_multiple), -        mPlugin(plugin->getSharedPrt()) -    { -    } - -    LLMediaFilePicker(LLPluginClassMedia* plugin, LLFilePicker::ESaveFilter filter, const std::string &proposed_name) -        : LLFilePickerThread(filter, proposed_name), -        mPlugin(plugin->getSharedPrt()) -    { -    } - -    virtual void notify(const std::vector<std::string>& filenames) -    { -        mPlugin->sendPickFileResponse(mResponses); -        mPlugin = NULL; -    } - -private: -    boost::shared_ptr<LLPluginClassMedia> mPlugin; -};  void init_threaded_picker_load_dialog(LLPluginClassMedia* plugin, LLFilePicker::ELoadFilter filter, bool get_multiple)  {      (new LLMediaFilePicker(plugin, filter, get_multiple))->getFile(); // will delete itself  } -void init_threaded_picker_save_dialog(LLPluginClassMedia* plugin, LLFilePicker::ESaveFilter filter, std::string &proposed_name) -{ -    (new LLMediaFilePicker(plugin, filter, proposed_name))->getFile(); // will delete itself -} -  ///////////////////////////////////////////////////////////////////////////////  // Move this to its own file. @@ -1778,6 +1749,10 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_  			// need to set agent string here before instance created  			media_source->setBrowserUserAgent(LLViewerMedia::getInstance()->getCurrentUserAgent()); +            // configure and pass proxy setup based on debug settings that are  +            // configured by UI in prefs -> setup +            media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); +  			media_source->setTarget(target);  			const std::string plugin_dir = gDirUtilp->getLLPluginDir(); @@ -1862,8 +1837,6 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)  		std::string ca_path = gDirUtilp->getCAFile();  		media_source->addCertificateFilePath( ca_path ); -		media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); -  		if(mClearCache)  		{  			mClearCache = false; @@ -3223,37 +3196,17 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla  			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << plugin->getCursorName() << LL_ENDL;  			std::string cursor = plugin->getCursorName(); - -			if(cursor == "arrow") -				mLastSetCursor = UI_CURSOR_ARROW; -			else if(cursor == "ibeam") -				mLastSetCursor = UI_CURSOR_IBEAM; -			else if(cursor == "splith") -				mLastSetCursor = UI_CURSOR_SIZEWE; -			else if(cursor == "splitv") -				mLastSetCursor = UI_CURSOR_SIZENS; -			else if(cursor == "hand") -				mLastSetCursor = UI_CURSOR_HAND; -			else // for anything else, default to the arrow -				mLastSetCursor = UI_CURSOR_ARROW; +			mLastSetCursor = getCursorFromString(cursor);  		}  		break;  		case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD:  		{  			LL_DEBUGS("Media") << "Media event - file download requested - filename is " << plugin->getFileDownloadFilename() << LL_ENDL; -			// pick a file from SAVE FILE dialog - -			// need a better algorithm that this or else, pass in type of save type -			// from event that initiated it - this is okay for now - only thing -			// that saves is 360s -			std::string suggested_filename = plugin->getFileDownloadFilename(); -			LLFilePicker::ESaveFilter filter = LLFilePicker::FFSAVE_ALL; -			if (suggested_filename.find(".jpg") != std::string::npos || suggested_filename.find(".jpeg") != std::string::npos) -				filter = LLFilePicker::FFSAVE_JPEG; -			if (suggested_filename.find(".png") != std::string::npos) -				filter = LLFilePicker::FFSAVE_PNG; -			init_threaded_picker_save_dialog(plugin, filter, suggested_filename); + +            //unblock media plugin +            const std::vector<std::string> empty_response; +            plugin->sendPickFileResponse(empty_response);  		}  		break; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c03f44e7ca..8b9acd6fb8 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -202,6 +202,7 @@ LLContextMenu* gDetachBodyPartPieMenus[9];  // File Menu  void handle_compress_image(void*); +void handle_compress_file_test(void*);  // Edit menu @@ -2224,6 +2225,21 @@ class LLAdvancedCompressImage : public view_listener_t  }; + +//////////////////////// +// COMPRESS FILE TEST // +//////////////////////// + +class LLAdvancedCompressFileTest : public view_listener_t +{ +    bool handleEvent(const LLSD& userdata) +    { +        handle_compress_file_test(NULL); +        return true; +    } +}; + +  /////////////////////////  // SHOW DEBUG SETTINGS //  ///////////////////////// @@ -6260,6 +6276,32 @@ class LLAvatarToggleMyProfile : public view_listener_t  	}  }; +class LLAvatarToggleSearch : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +		LLFloater* instance = LLFloaterReg::findInstance("search"); +		if (LLFloater::isMinimized(instance)) +		{ +			instance->setMinimized(FALSE); +			instance->setFocus(TRUE); +		} +		else if (!LLFloater::isShown(instance)) +		{ +			LLFloaterReg::showInstance("search"); +		} +		else if (!instance->hasFocus() && !instance->getIsChrome()) +		{ +			instance->setFocus(TRUE); +		} +		else +		{ +			instance->closeFloater(); +		} +		return true; +	} +}; +  class LLAvatarResetSkeleton: public view_listener_t  {      bool handleEvent(const LLSD& userdata) @@ -9344,6 +9386,7 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates");  	view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates");  	view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage"); +    view_listener_t::addMenu(new LLAdvancedCompressFileTest(), "Advanced.CompressFileTest");  	view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");  	view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions");  	view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions"); @@ -9408,6 +9451,7 @@ void initialize_menus()  	enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall));  	view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");  	view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile"); +	view_listener_t::addMenu(new LLAvatarToggleSearch(), "Avatar.ToggleSearch");  	view_listener_t::addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton");  	view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton");  	view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 4efc3d1cb3..28ff69eaf5 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -46,6 +46,7 @@  #include "llimagejpeg.h"  #include "llimagetga.h"  #include "llinventorymodel.h"	// gInventory +#include "llpluginclassmedia.h"  #include "llresourcedata.h"  #include "lltoast.h"  #include "llfloaterperms.h" @@ -251,6 +252,25 @@ void LLFilePickerReplyThread::notify(const std::vector<std::string>& filenames)  	}  } + +LLMediaFilePicker::LLMediaFilePicker(LLPluginClassMedia* plugin, LLFilePicker::ELoadFilter filter, bool get_multiple) +    : LLFilePickerThread(filter, get_multiple), +    mPlugin(plugin->getSharedPrt()) +{ +} + +LLMediaFilePicker::LLMediaFilePicker(LLPluginClassMedia* plugin, LLFilePicker::ESaveFilter filter, const std::string &proposed_name) +    : LLFilePickerThread(filter, proposed_name), +    mPlugin(plugin->getSharedPrt()) +{ +} + +void LLMediaFilePicker::notify(const std::vector<std::string>& filenames) +{ +    mPlugin->sendPickFileResponse(mResponses); +    mPlugin = NULL; +} +  //============================================================================  #if LL_WINDOWS @@ -549,13 +569,8 @@ class LLFileUploadModel : public view_listener_t  {  	bool handleEvent(const LLSD& userdata)  	{ -		LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::getInstance("upload_model"); -		if (fmp && !fmp->isModelLoading()) -		{ -			fmp->loadHighLodModel(); -		} -		 -		return TRUE; +        LLFloaterModelPreview::showModelPreview(); +        return TRUE;  	}  }; @@ -773,6 +788,94 @@ void handle_compress_image(void*)  	}  } +// No convinient check in LLFile, and correct way would be something +// like GetFileSizeEx, which is too OS specific for current purpose +// so doing dirty, but OS independent fopen and fseek +size_t get_file_size(std::string &filename) +{ +    LLFILE* file = LLFile::fopen(filename, "rb");		/*Flawfinder: ignore*/ +    if (!file) +    { +        LL_WARNS() << "Error opening " << filename << LL_ENDL; +        return 0; +    } + +    // read in the whole file +    fseek(file, 0L, SEEK_END); +    size_t file_length = (size_t)ftell(file); +    fclose(file); +    return file_length; +} + +void handle_compress_file_test(void*) +{ +    LLFilePicker& picker = LLFilePicker::instance(); +    if (picker.getOpenFile()) +    { +        std::string infile = picker.getFirstFile(); +        if (!infile.empty()) +        { +            std::string packfile = infile + ".pack_test"; +            std::string unpackfile = infile + ".unpack_test"; + +            S64Bytes initial_size = S64Bytes(get_file_size(infile)); + +            BOOL success; + +            F64 total_seconds = LLTimer::getTotalSeconds(); +            success = gzip_file(infile, packfile); +            F64 result_pack_seconds = LLTimer::getTotalSeconds() - total_seconds; + +            if (success) +            { +                S64Bytes packed_size = S64Bytes(get_file_size(packfile)); + +                LL_INFOS() << "Packing complete, time: " << result_pack_seconds << " size: " << packed_size << LL_ENDL; +                total_seconds = LLTimer::getTotalSeconds(); +                success = gunzip_file(packfile, unpackfile); +                F64 result_unpack_seconds = LLTimer::getTotalSeconds() - total_seconds; + +                if (success) +                { +                    S64Bytes unpacked_size = S64Bytes(get_file_size(unpackfile)); + +                    LL_INFOS() << "Unpacking complete, time: " << result_unpack_seconds << " size: " << unpacked_size << LL_ENDL; + +                    LLSD args; +                    args["FILE"] = infile; +                    args["PACK_TIME"] = result_pack_seconds; +                    args["UNPACK_TIME"] = result_unpack_seconds; +                    args["SIZE"] = LLSD::Integer(initial_size.valueInUnits<LLUnits::Kilobytes>()); +                    args["PSIZE"] = LLSD::Integer(packed_size.valueInUnits<LLUnits::Kilobytes>()); +                    args["USIZE"] = LLSD::Integer(unpacked_size.valueInUnits<LLUnits::Kilobytes>()); +                    LLNotificationsUtil::add("CompressionTestResults", args); + +                    LLFile::remove(packfile); +                    LLFile::remove(unpackfile); +                } +                else +                { +                    LL_INFOS() << "Failed to uncompress file: " << packfile << LL_ENDL; +                    LLFile::remove(packfile); +                } + +            } +            else +            { +                LL_INFOS() << "Failed to compres file: " << infile << LL_ENDL; +            } +        } +        else +        { +            LL_INFOS() << "Failed to open file" << LL_ENDL; +        } +    } +    else +    { +        LL_INFOS() << "Failed to open file" << LL_ENDL; +    } +} +  LLUUID upload_new_resource(  	const std::string& src_filename, diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 4e6250d9b4..beeac418d9 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -37,6 +37,7 @@  #include "llviewerassetupload.h"  class LLTransactionID; +class LLPluginClassMedia;  void init_menu_file(); @@ -71,6 +72,7 @@ void assign_defaults_and_show_upload_message(  	const std::string& display_name,  	std::string& description); +//consider moving all file pickers below to more suitable place  class LLFilePickerThread : public LLThread  { //multi-threaded file picker (runs system specific file picker in background and calls "notify" from main thread)  public: @@ -127,5 +129,17 @@ private:  	file_picked_signal_t*		mFailureSignal;  }; +class LLMediaFilePicker : public LLFilePickerThread +{ +public: +    LLMediaFilePicker(LLPluginClassMedia* plugin, LLFilePicker::ELoadFilter filter, bool get_multiple); +    LLMediaFilePicker(LLPluginClassMedia* plugin, LLFilePicker::ESaveFilter filter, const std::string &proposed_name); + +    virtual void notify(const std::vector<std::string>& filenames); + +private: +    boost::shared_ptr<LLPluginClassMedia> mPlugin; +}; +  #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 22e5907b14..a886303563 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3849,7 +3849,12 @@ void process_sound_trigger(LLMessageSystem *msg, void **)  	}  	// Don't play sounds from gestures if they are not enabled. -	if (object_id == owner_id && !gSavedSettings.getBOOL("EnableGestureSounds")) +	// Do play sounds triggered by avatar, since muting your own +	// gesture sounds and your own sounds played inworld from  +	// Inventory can cause confusion. +	if (object_id == owner_id +        && owner_id != gAgentID +        && !gSavedSettings.getBOOL("EnableGestureSounds"))  	{  		return;  	} diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 0f409701d1..27fbf39673 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -242,9 +242,9 @@ public:  	LLVector3   mLastCameraOrigin;  	U32         mLastCameraUpdate; -    void        requestBaseCapabilitiesCoro(U64 regionHandle); -    void        requestBaseCapabilitiesCompleteCoro(U64 regionHandle); -    void        requestSimulatorFeatureCoro(std::string url, U64 regionHandle); +    static void        requestBaseCapabilitiesCoro(U64 regionHandle); +    static void        requestBaseCapabilitiesCompleteCoro(U64 regionHandle); +    static void        requestSimulatorFeatureCoro(std::string url, U64 regionHandle);  };  void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) @@ -272,6 +272,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)              LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL;              return; // this error condition is not recoverable.          } +        LLViewerRegionImpl* impl = regionp->getRegionImplNC();          LL_DEBUGS("AppInit", "Capabilities") << "requesting seed caps for handle " << regionHandle                                                << " name " << regionp->getName() << LL_ENDL; @@ -286,32 +287,33 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)          newRegionEntry(*regionp);          // After a few attempts, continue login.  But keep trying to get the caps: -        if (mSeedCapAttempts >= mSeedCapMaxAttemptsBeforeLogin && +        if (impl->mSeedCapAttempts >= impl->mSeedCapMaxAttemptsBeforeLogin &&              STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())          {              LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED);          } -        if (mSeedCapAttempts > mSeedCapMaxAttempts) +        if (impl->mSeedCapAttempts > impl->mSeedCapMaxAttempts)          {              // *TODO: Give a user pop-up about this error? -            LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mSeedCapAttempts << " attempts.  Giving up!" << LL_ENDL; +            LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << impl->mSeedCapAttempts << " attempts.  Giving up!" << LL_ENDL;              return;  // this error condition is not recoverable.          } -        S32 id = ++mHttpResponderID; +        S32 id = ++(impl->mHttpResponderID);          LLSD capabilityNames = LLSD::emptyArray(); -        buildCapabilityNames(capabilityNames); +        impl->buildCapabilityNames(capabilityNames);          LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url                                               << " region name " << regionp->getName()                                              << " region id " << regionp->getRegionID()                                              << " handle " << regionp->getHandle() -                                            << " (attempt #" << mSeedCapAttempts + 1 << ")" << LL_ENDL; +                                            << " (attempt #" << impl->mSeedCapAttempts + 1 << ")" << LL_ENDL;  		LL_DEBUGS("AppInit", "Capabilities") << "Capabilities requested: " << capabilityNames << LL_ENDL;          regionp = NULL; +        impl = NULL;          result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);          if (STATE_WORLD_INIT > LLStartUp::getStartupState()) @@ -325,8 +327,6 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)              return;          } -        ++mSeedCapAttempts; -          regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);          if (!regionp) //region was removed          { @@ -334,7 +334,11 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)              return; // this error condition is not recoverable.          } -        if (id != mHttpResponderID) // region is no longer referring to this request +        impl = regionp->getRegionImplNC(); + +        ++impl->mSeedCapAttempts; + +        if (id != impl->mHttpResponderID) // region is no longer referring to this request          {              LL_WARNS("AppInit", "Capabilities") << "Received results for a stale capabilities request!" << LL_ENDL;              // setup for retry. @@ -391,7 +395,6 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)      {   // *HACK: we're waiting for the ServerReleaseNotes          regionp->showReleaseNotes();      } -  } @@ -452,6 +455,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)              LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL;              break; // this error condition is not recoverable.          } +        LLViewerRegionImpl* impl = regionp->getRegionImplNC();          // remove the http_result from the llsd          result.erase("http_result"); @@ -464,30 +468,30 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)          }  #if 0 -        log_capabilities(mCapabilities); +        log_capabilities(impl->mCapabilities);  #endif -        if (mCapabilities.size() != mSecondCapabilitiesTracker.size()) +        if (impl->mCapabilities.size() != impl->mSecondCapabilitiesTracker.size())          {              LL_WARNS("AppInit", "Capabilities")                  << "Sim sent duplicate base caps that differ in size from what we initially received - most likely content. " -                << "mCapabilities == " << mCapabilities.size() -                << " mSecondCapabilitiesTracker == " << mSecondCapabilitiesTracker.size() +                << "mCapabilities == " << impl->mCapabilities.size() +                << " mSecondCapabilitiesTracker == " << impl->mSecondCapabilitiesTracker.size()                  << LL_ENDL;  #ifdef DEBUG_CAPS_GRANTS              LL_WARNS("AppInit", "Capabilities")                  << "Initial Base capabilities: " << LL_ENDL; -            log_capabilities(mCapabilities); +            log_capabilities(impl->mCapabilities);              LL_WARNS("AppInit", "Capabilities")                  << "Latest base capabilities: " << LL_ENDL; -            log_capabilities(mSecondCapabilitiesTracker); +            log_capabilities(impl->mSecondCapabilitiesTracker);  #endif -            if (mSecondCapabilitiesTracker.size() > mCapabilities.size()) +            if (impl->mSecondCapabilitiesTracker.size() > impl->mCapabilities.size())              {                  // *HACK Since we were granted more base capabilities in this grant request than the initial, replace                  // the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a @@ -495,19 +499,17 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)                  // inventory api capability grants.                  // Need to clear a std::map before copying into it because old keys take precedence. -                mCapabilities.clear(); -                mCapabilities = mSecondCapabilitiesTracker; +                impl->mCapabilities.clear(); +                impl->mCapabilities = impl->mSecondCapabilitiesTracker;              }          }          else          {              LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL;          } -        mSecondCapabilitiesTracker.clear(); +        impl->mSecondCapabilitiesTracker.clear();      }       while (false); - -  }  void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 regionHandle) @@ -1451,7 +1453,12 @@ void LLViewerRegion::clearCachedVisibleObjects()  	for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.begin();  		iter != mImpl->mActiveSet.end(); ++iter)  	{ -		LLDrawable* drawablep = (LLDrawable*)(*iter)->getEntry()->getDrawable(); +        LLVOCacheEntry* vo_entry = *iter; +        if (!vo_entry || !vo_entry->getEntry()) +        { +            continue; +        } +        LLDrawable* drawablep = (LLDrawable*)vo_entry->getEntry()->getDrawable();  		if(drawablep && !drawablep->getParent())  		{ @@ -2242,7 +2249,7 @@ void LLViewerRegion::requestSimulatorFeatures()      {          std::string coroname =              LLCoros::instance().launch("LLViewerRegionImpl::requestSimulatorFeatureCoro", -                                       boost::bind(&LLViewerRegionImpl::requestSimulatorFeatureCoro, mImpl, url, getHandle())); +                                       boost::bind(&LLViewerRegionImpl::requestSimulatorFeatureCoro, url, getHandle()));          LL_INFOS("AppInit", "SimulatorFeatures") << "Launching " << coroname << " requesting simulator features from " << url << " for region " << getRegionID() << LL_ENDL;      } @@ -3060,7 +3067,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  		//to the "original" seed cap received and determine why there is problem!          std::string coroname =              LLCoros::instance().launch("LLEnvironmentRequest::requestBaseCapabilitiesCompleteCoro", -            boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro, mImpl, getHandle())); +            boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro, getHandle()));  		return;      } @@ -3072,7 +3079,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)      std::string coroname =          LLCoros::instance().launch("LLViewerRegionImpl::requestBaseCapabilitiesCoro", -        boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCoro, mImpl, getHandle())); +        boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCoro, getHandle()));      LL_INFOS("AppInit", "Capabilities") << "Launching " << coroname << " requesting seed capabilities from " << url << " for region " << getRegionID() << LL_ENDL;  } diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index a560778ef4..5484d43b8d 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -62,6 +62,7 @@  #include "llsdutil.h"  #include "llcorehttputil.h"  #include "llvoicevivox.h" +#include "llinventorymodel.h"  #include "lluiusage.h"  namespace LLStatViewer @@ -206,6 +207,7 @@ LLTrace::EventStatHandle<F64Seconds >	AVATAR_EDIT_TIME("avataredittime", "Second  LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT_RATE("object_cache_hits"); +LLTrace::EventStatHandle<F64Seconds >	TEXTURE_FETCH_TIME("texture_fetch_time");  }  LLViewerStats::LLViewerStats()  @@ -389,15 +391,6 @@ void update_statistics()  	add(LLStatViewer::ASSET_UDP_DATA_RECEIVED, F64Bits(gTransferManager.getTransferBitsIn(LLTCT_ASSET)));  	gTransferManager.resetTransferBitsIn(LLTCT_ASSET); -	if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) -	{ -		gTextureTimer.pause(); -	} -	else -	{ -		gTextureTimer.unpause(); -	} -	  	sample(LLStatViewer::VISIBLE_AVATARS, LLVOAvatar::sNumVisibleAvatars);  	LLWorld::getInstance()->updateNetStats();  	LLWorld::getInstance()->requestCacheMisses(); @@ -419,6 +412,19 @@ void update_statistics()  	}  } +void update_texture_time() +{ +	if (gTextureList.isPrioRequestsFetched()) +	{ +		gTextureTimer.pause(); +	} +	else +	{		 +		gTextureTimer.unpause(); +	} + +	record(LLStatViewer::TEXTURE_FETCH_TIME, gTextureTimer.getElapsedTimeF32()); +}  /*   * The sim-side LLSD is in newsim/llagentinfo.cpp:forwardViewerStats.   * @@ -580,6 +586,11 @@ void send_viewer_stats(bool include_preferences)  	fail["invalid"] = (S32) gMessageSystem->mInvalidOnCircuitPackets;  	fail["missing_updater"] = (S32) LLAppViewer::instance()->isUpdaterMissing(); +	LLSD &inventory = body["inventory"]; +	inventory["usable"] = gInventory.isInventoryUsable(); +	LLSD& validation_info = inventory["validation_info"]; +	gInventory.mValidationInfo->asLLSD(validation_info); +  	body["ui"] = LLUIUsage::instance().asLLSD();  	body["stats"]["voice"] = LLVoiceVivoxStats::getInstance()->read(); diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 1133326d4f..017c79b2e3 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -294,6 +294,7 @@ static const F32 SEND_STATS_PERIOD = 300.0f;  // The following are from (older?) statistics code found in appviewer.  void update_statistics();  void send_viewer_stats(bool include_preferences); +void update_texture_time();  extern LLFrameTimer gTextureTimer;  extern U32Bytes	gTotalTextureData; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 03b5b7497f..b953d7006b 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -423,6 +423,7 @@ public:  	BOOL		isFullyLoaded() const;  	BOOL        hasFetcher() const { return mHasFetcher;} +	bool        isFetching() const { return mIsFetching;}  	void        setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;}  	void        forceToDeleteRequest(); diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index dd18cdc9e8..f9fd0f85e3 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -204,6 +204,9 @@ static std::string get_texture_list_name()  void LLViewerTextureList::doPrefetchImages()  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; +    gTextureTimer.start(); +    gTextureTimer.pause(); +  	if (LLAppViewer::instance()->getPurgeCache())  	{  		// cache was purged, no point @@ -1401,6 +1404,33 @@ S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, fl  	return max_texmem;  } +bool LLViewerTextureList::isPrioRequestsFetched() +{ +	static LLCachedControl<F32> prio_threshold(gSavedSettings, "TextureFetchUpdatePriorityThreshold", 0.0f); +	static LLCachedControl<F32> fetching_textures_threshold(gSavedSettings, "TextureListFetchingThreshold", 0.97f); +	S32 fetching_tex_count = 0; +	S32 tex_count_threshold = gTextureList.mImageList.size() * (1 - fetching_textures_threshold); + +	for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin(); +		iter != gTextureList.mImageList.end(); ) +	{ +		LLPointer<LLViewerFetchedTexture> imagep = *iter++; +		if (imagep->getDecodePriority() > prio_threshold) +		{ +			if (imagep->hasFetcher() || imagep->isFetching()) +			{ +				fetching_tex_count++; +				if (fetching_tex_count >= tex_count_threshold) +				{ +					return false; +				} +			} +		} +	} + +	return true; +} +  const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM(12);  const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(512);  void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem) diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 281d23c671..fead2e52b2 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -138,6 +138,8 @@ public:  	static S32Megabytes getMinVideoRamSetting();  	static S32Megabytes getMaxVideoRamSetting(bool get_recommended, float mem_multiplier); + +	static bool isPrioRequestsFetched();  private:  	void updateImagesDecodePriorities(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b9a5e90df0..5487f0851e 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -215,6 +215,7 @@  #if LL_WINDOWS  #include <tchar.h> // For Unicode conversion methods +#include "llwindowwin32.h" // For AltGr handling  #endif  // @@ -2870,57 +2871,64 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)      if (keyboard_focus          && !gFocusMgr.getKeystrokesOnly())      { -#ifdef LL_WINDOWS -        // On windows Alt Gr key generates additional Ctrl event, as result handling situations -        // like 'AltGr + D' will result in 'Alt+Ctrl+D'. If it results in WM_CHAR, don't let it -        // pass into menu or it will trigger 'develop' menu assigned to this combination on top -        // of character handling. -        // Alt Gr can be additionally modified by Shift -        const MASK alt_gr = MASK_CONTROL | MASK_ALT; -        if ((mask & alt_gr) != 0 -            && key >= 0x30 -            && key <= 0x5A -            && (GetKeyState(VK_RMENU) & 0x8000) != 0 -            && (GetKeyState(VK_RCONTROL) & 0x8000) == 0) // ensure right control is not pressed, only left one +        LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(keyboard_focus); +        if (cur_focus && cur_focus->acceptsTextInput())          { -            // Alt Gr key is represented as right alt and left control. -            // Any alt+ctrl combination is treated as Alt Gr by TranslateMessage() and -            // will generate a WM_CHAR message, but here we only treat virtual Alt Graph -            // key by checking if this specific combination has unicode char. -            // -            // I decided to handle only virtual RAlt+LCtrl==AltGr combination to minimize -            // impact on menu, but the right way might be to handle all Alt+Ctrl calls. - -            BYTE keyboard_state[256]; -            if (GetKeyboardState(keyboard_state)) +#ifdef LL_WINDOWS +            // On windows Alt Gr key generates additional Ctrl event, as result handling situations +            // like 'AltGr + D' will result in 'Alt+Ctrl+D'. If it results in WM_CHAR, don't let it +            // pass into menu or it will trigger 'develop' menu assigned to this combination on top +            // of character handling. +            // Alt Gr can be additionally modified by Shift +            const MASK alt_gr = MASK_CONTROL | MASK_ALT; +            LLWindowWin32 *window = static_cast<LLWindowWin32*>(mWindow); +            U32 raw_key = window->getRawWParam(); +            if ((mask & alt_gr) != 0 +                && ((raw_key >= 0x30 && raw_key <= 0x5A) //0-9, plus normal chartacters +                    || (raw_key >= 0xBA && raw_key <= 0xE4)) // Misc/OEM characters that can be covered by AltGr, ex: -, =, ~ +                && (GetKeyState(VK_RMENU) & 0x8000) != 0 +                && (GetKeyState(VK_RCONTROL) & 0x8000) == 0) // ensure right control is not pressed, only left one              { -                const int char_count = 6; -                wchar_t chars[char_count]; -                HKL layout = GetKeyboardLayout(0); -                // ToUnicodeEx changes buffer state on OS below Win10, which is undesirable, -                // but since we already did a TranslateMessage() in gatherInput(), this -                // should have no negative effect -                int res = ToUnicodeEx(key, 0, keyboard_state, chars, char_count, 1 << 2 /*do not modify buffer flag*/, layout); -                if (res == 1 && chars[0] >= 0x20) +                // Alt Gr key is represented as right alt and left control. +                // Any alt+ctrl combination is treated as Alt Gr by TranslateMessage() and +                // will generate a WM_CHAR message, but here we only treat virtual Alt Graph +                // key by checking if this specific combination has unicode char. +                // +                // I decided to handle only virtual RAlt+LCtrl==AltGr combination to minimize +                // impact on menu, but the right way might be to handle all Alt+Ctrl calls. + +                BYTE keyboard_state[256]; +                if (GetKeyboardState(keyboard_state))                  { -                    // Let it fall through to character handler and get a WM_CHAR. -                    return TRUE; +                    const int char_count = 6; +                    wchar_t chars[char_count]; +                    HKL layout = GetKeyboardLayout(0); +                    // ToUnicodeEx changes buffer state on OS below Win10, which is undesirable, +                    // but since we already did a TranslateMessage() in gatherInput(), this +                    // should have no negative effect +                    // ToUnicodeEx works with virtual key codes +                    int res = ToUnicodeEx(raw_key, 0, keyboard_state, chars, char_count, 1 << 2 /*do not modify buffer flag*/, layout); +                    if (res == 1 && chars[0] >= 0x20) +                    { +                        // Let it fall through to character handler and get a WM_CHAR. +                        return TRUE; +                    }                  }              } -        }  #endif -        if (!(mask & (MASK_CONTROL | MASK_ALT))) -        { -            // We have keyboard focus, and it's not an accelerator -            if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown()) -            { -                return keyboard_focus->handleKey(key, mask, FALSE); -            } -            else if (key < 0x80) +            if (!(mask & (MASK_CONTROL | MASK_ALT)))              { -                // Not a special key, so likely (we hope) to generate a character.  Let it fall through to character handler first. -                return TRUE; +                // We have keyboard focus, and it's not an accelerator +                if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown()) +                { +                    return keyboard_focus->handleKey(key, mask, FALSE); +                } +                else if (key < 0x80) +                { +                    // Not a special key, so likely (we hope) to generate a character.  Let it fall through to character handler first. +                    return TRUE; +                }              }          }      } diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 3d503638e0..19036a3f77 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -89,6 +89,7 @@ namespace {      // Don't retry connecting to the daemon more frequently than this:      const F32 DAEMON_CONNECT_THROTTLE_SECONDS = 1.0f; +    const int DAEMON_CONNECT_RETRY_MAX = 3;      // Don't send positional updates more frequently than this:      const F32 UPDATE_THROTTLE_SECONDS = 0.5f; @@ -705,6 +706,11 @@ void LLVivoxVoiceClient::voiceControlCoro()  void LLVivoxVoiceClient::voiceControlStateMachine(S32 &coro_state)  { +    if (sShuttingDown) +    { +        return; +    } +      LL_DEBUGS("Voice") << "starting" << LL_ENDL;      mIsCoroutineActive = true;      LLCoros::set_consuming(true); @@ -860,6 +866,12 @@ void LLVivoxVoiceClient::voiceControlStateMachine(S32 &coro_state)          }      } while (coro_state > 0); +    if (sShuttingDown) +    { +        // LLVivoxVoiceClient might be already dead +        return; +    } +      mIsCoroutineActive = false;      LL_INFOS("Voice") << "exiting" << LL_ENDL;  } @@ -1033,8 +1045,9 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()      LL_DEBUGS("Voice") << "Connecting to vivox daemon:" << mDaemonHost << LL_ENDL; +    int retryCount(0);      LLVoiceVivoxStats::getInstance()->reset(); -    while (!mConnected && !sShuttingDown) +    while (!mConnected && !sShuttingDown && retryCount++ <= DAEMON_CONNECT_RETRY_MAX)      {          LLVoiceVivoxStats::getInstance()->connectionAttemptStart();          LL_DEBUGS("Voice") << "Attempting to connect to vivox daemon: " << mDaemonHost << LL_ENDL; @@ -1160,7 +1173,7 @@ bool LLVivoxVoiceClient::provisionVoiceAccount()          {              provisioned = true;          }         -    } while (!provisioned && retryCount <= PROVISION_RETRY_MAX && !sShuttingDown); +    } while (!provisioned && ++retryCount <= PROVISION_RETRY_MAX && !sShuttingDown);      if (sShuttingDown && !provisioned)      { @@ -1343,6 +1356,12 @@ bool LLVivoxVoiceClient::loginToVivox()          }          LLSD result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGIN_ATTEMPT_TIMEOUT, timeoutResult); + +        if (sShuttingDown) +        { +            return false; +        } +          LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;          if (result.has("login")) @@ -1405,6 +1424,11 @@ bool LLVivoxVoiceClient::loginToVivox()      } while ((!response_ok || !account_login) && !sShuttingDown); +    if (sShuttingDown) +    { +        return false; +    } +      mRelogRequested = false;      mIsLoggedIn = true;      notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e8bc015d78..4d72dc8776 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5972,6 +5972,8 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  				if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )  				{  					LLVOVolume* vobj = drawablep->getVOVolume(); +                    if (!vobj) continue; +  					if (debugLoggingEnabled("AnimatedObjectsLinkset"))  					{  						if (vobj->isAnimatedObject() && vobj->isRiggedMesh()) @@ -5991,6 +5993,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  					}  					LLVolume* volume = vobj->getVolume(); +                    if (!volume) continue;  					for (S32 i = 0; i < drawablep->getNumFaces(); ++i)  					{  						LLFace* face = drawablep->getFace(i); diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp index bae615232e..4401f61059 100644 --- a/indra/newview/llxmlrpclistener.cpp +++ b/indra/newview/llxmlrpclistener.cpp @@ -421,59 +421,109 @@ private:              std::string key(XMLRPC_GetValueID(current));              LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL;              XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(current); -            if (xmlrpc_type_string == type) +            switch (type)              { -                LLSD::String val(XMLRPC_GetValueString(current)); -                LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; -                responses.insert(key, val); -            } -            else if (xmlrpc_type_int == type) -            { -                LLSD::Integer val(XMLRPC_GetValueInt(current)); -                LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; -                responses.insert(key, val); -            } -            else if (xmlrpc_type_double == type) -            { -                LLSD::Real val(XMLRPC_GetValueDouble(current)); -                LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; -                responses.insert(key, val); -            } -            else if (xmlrpc_type_array == type) -            { -                // We expect this to be an array of submaps. Walk the array, -                // recursively parsing each submap and collecting them. -                LLSD array; -                int i = 0;          // for descriptive purposes -                for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row; -                     row = XMLRPC_VectorNext(current), ++i) +            case xmlrpc_type_empty: +                LL_INFOS("LLXMLRPCListener") << "Empty result for key " << key_pfx << key << LL_ENDL; +                responses.insert(key, LLSD()); +                break; +            case xmlrpc_type_base64:                  { -                    // Recursive call. For the lower-level key_pfx, if 'key' -                    // is "foo", pass "foo[0]:", then "foo[1]:", etc. In the -                    // nested call, a subkey "bar" will then be logged as -                    // "foo[0]:bar", and so forth. -                    // Parse the scalar subkey/value pairs from this array -                    // entry into a temp submap. Collect such submaps in 'array'. -                    array.append(parseValues(status_string, -                                             STRINGIZE(key_pfx << key << '[' << i << "]:"), -                                             row)); +                    S32 len = XMLRPC_GetValueStringLen(current); +                    const char* buf = XMLRPC_GetValueBase64(current); +                    if ((len > 0) && buf) +                    { +                        // During implementation this code was not tested +                        // If you encounter this, please make sure this is correct, +                        // then remove llassert +                        llassert(0); + +                        LLSD::Binary data; +                        data.resize(len); +                        memcpy((void*)&data[0], (void*)buf, len); +                        responses.insert(key, data); +                    } +                    else +                    { +                        LL_WARNS("LLXMLRPCListener") << "Potentially malformed xmlrpc_type_base64 for key " +                            << key_pfx << key << LL_ENDL; +                        responses.insert(key, LLSD()); +                    } +                    break;                  } -                // Having collected an 'array' of 'submap's, insert that whole -                // 'array' as the value of this 'key'. -                responses.insert(key, array); -            } -            else if (xmlrpc_type_struct == type) -            { -                LLSD submap = parseValues(status_string, -                                          STRINGIZE(key_pfx << key << ':'), -                                          current); -                responses.insert(key, submap); -            } -            else -            { +            case xmlrpc_type_boolean: +                { +                    LLSD::Boolean val(XMLRPC_GetValueBoolean(current)); +                    LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; +                    responses.insert(key, val); +                    break; +                } +            case xmlrpc_type_datetime: +                { +                    std::string iso8601_date(XMLRPC_GetValueDateTime_ISO8601(current)); +                    LL_DEBUGS("LLXMLRPCListener") << "val: " << iso8601_date << LL_ENDL; +                    responses.insert(key, LLSD::Date(iso8601_date)); +                    break; +                } +            case xmlrpc_type_double: +                { +                    LLSD::Real val(XMLRPC_GetValueDouble(current)); +                    LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; +                    responses.insert(key, val); +                    break; +                } +            case xmlrpc_type_int: +                { +                    LLSD::Integer val(XMLRPC_GetValueInt(current)); +                    LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; +                    responses.insert(key, val); +                    break; +                } +            case xmlrpc_type_string: +                { +                    LLSD::String val(XMLRPC_GetValueString(current)); +                    LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; +                    responses.insert(key, val); +                    break; +                } +            case xmlrpc_type_mixed: +            case xmlrpc_type_array: +                { +                    // We expect this to be an array of submaps. Walk the array, +                    // recursively parsing each submap and collecting them. +                    LLSD array; +                    int i = 0;          // for descriptive purposes +                    for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row; +                         row = XMLRPC_VectorNext(current), ++i) +                    { +                        // Recursive call. For the lower-level key_pfx, if 'key' +                        // is "foo", pass "foo[0]:", then "foo[1]:", etc. In the +                        // nested call, a subkey "bar" will then be logged as +                        // "foo[0]:bar", and so forth. +                        // Parse the scalar subkey/value pairs from this array +                        // entry into a temp submap. Collect such submaps in 'array'. +                        array.append(parseValues(status_string, +                                                 STRINGIZE(key_pfx << key << '[' << i << "]:"), +                                                 row)); +                    } +                    // Having collected an 'array' of 'submap's, insert that whole +                    // 'array' as the value of this 'key'. +                    responses.insert(key, array); +                    break; +                } +            case xmlrpc_type_struct: +                { +                    LLSD submap = parseValues(status_string, +                                              STRINGIZE(key_pfx << key << ':'), +                                              current); +                    responses.insert(key, submap); +                    break; +                } +            case xmlrpc_type_none: // Not expected +            default:                  // whoops - unrecognized type                  LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key " -                                             << key_pfx << key << LL_ENDL; +                    << key_pfx << key << LL_ENDL;                  responses.insert(key, STRINGIZE("<bad XMLRPC type " << type << '>'));                  status_string = "BadType";              } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 6738532bc3..a6fa58f476 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6999,6 +6999,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,  		{  			if ((j == LLViewerRegion::PARTITION_VOLUME) ||   				(j == LLViewerRegion::PARTITION_BRIDGE) || +                (j == LLViewerRegion::PARTITION_AVATAR) || // for attachments  				(j == LLViewerRegion::PARTITION_CONTROL_AV) ||  				(j == LLViewerRegion::PARTITION_TERRAIN) ||  				(j == LLViewerRegion::PARTITION_TREE) || diff --git a/indra/newview/res-sdl/lltoolzoomout.BMP b/indra/newview/res-sdl/lltoolzoomout.BMPBinary files differ index 7f958383ab..5bdf96f80d 100644 --- a/indra/newview/res-sdl/lltoolzoomout.BMP +++ b/indra/newview/res-sdl/lltoolzoomout.BMP diff --git a/indra/newview/res-sdl/sizeall.BMP b/indra/newview/res-sdl/sizeall.BMPBinary files differ new file mode 100644 index 0000000000..03d9bf4654 --- /dev/null +++ b/indra/newview/res-sdl/sizeall.BMP diff --git a/indra/newview/res/lltoolzoomout.cur b/indra/newview/res/lltoolzoomout.curBinary files differ index b33e68d1a6..21e0ee9702 100644 --- a/indra/newview/res/lltoolzoomout.cur +++ b/indra/newview/res/lltoolzoomout.cur diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index ff2d8b4943..4ee26a312a 100755 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -99,6 +99,7 @@ END  TOOLGRAB                CURSOR                  "lltoolgrab.cur"  TOOLLAND                CURSOR                  "lltoolland.cur"  TOOLZOOMIN              CURSOR                  "lltoolzoomin.cur" +TOOLZOOMOUT             CURSOR                  "lltoolzoomout.cur"  TOOLCREATE              CURSOR                  "lltoolcreate.cur"  ARROWDRAG               CURSOR                  "llarrowdrag.cur"  ARROW                   CURSOR                  "llarrow.cur" diff --git a/indra/newview/skins/default/xui/da/menu_place_add_button.xml b/indra/newview/skins/default/xui/da/menu_place_add_button.xml index 7ad2253550..c43ec6b1b7 100644 --- a/indra/newview/skins/default/xui/da/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/da/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Opret mappe" name="add_folder"/>  	<menu_item_call label="Tilføj landemærke" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/da/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/da/menu_teleport_history_item.xml index dbaec62087..825ab056d9 100644 --- a/indra/newview/skins/default/xui/da/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/da/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Teleportér" name="Teleport"/>  	<menu_item_call label="Mere information" name="More Information"/>  	<menu_item_call label="Kopiér til udklipsholder" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/de/menu_place_add_button.xml b/indra/newview/skins/default/xui/de/menu_place_add_button.xml index 7c0ff4a46a..975e5b4497 100644 --- a/indra/newview/skins/default/xui/de/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/de/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Ordner hinzufügen" name="add_folder"/>  	<menu_item_call label="Landmarke hinzufügen" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/de/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/de/menu_teleport_history_item.xml index 1d7e3059c0..8f3bf84151 100644 --- a/indra/newview/skins/default/xui/de/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/de/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Teleportieren" name="Teleport"/>  	<menu_item_call label="Weitere Informationen" name="More Information"/>  	<menu_item_call label="SLurl kopieren" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml index c609e3bd3a..31c524c38a 100644 --- a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml +++ b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml @@ -342,6 +342,7 @@                                              width="25">                                          <button                                                  name="skip_back_btn" +                                                enabled="false"                                                  follows="top"                                                  image_overlay="SkipBackward_Off"                                                  image_disabled="PushButton_Disabled" @@ -373,6 +374,7 @@                                              width="25">                                          <button                                                  name="play_btn" +                                                enabled="false"                                                  follows="top"                                                  image_overlay="Play_Off"                                                  image_disabled="PushButton_Disabled" @@ -434,6 +436,7 @@                                              width="25">                                          <button                                                  name="skip_forward_btn" +                                                enabled="false"                                                  follows="top"                                                  image_overlay="SkipForward_Off"                                                  image_disabled="PushButton_Disabled" 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 f10cc61826..ca3e40465c 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -1670,7 +1670,7 @@ Analysed:           wrap="true"           width="462"           visible="true"> -         You dont have rights to upload mesh models. [[VURL] Find out how] to get certified. +         You don't have rights to upload mesh models. [[VURL] Find out how] to get certified.         </text>          <text           text_color="Yellow" 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 3ea5f54f2c..d1f8da55be 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_animation.xml @@ -1,66 +1,126 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <floater   legacy_header_height="18" - height="85" + height="241"   layout="topleft"   name="preview_anim"   help_topic="preview_anim" - width="280"> + width="320">      <floater.string       name="Title">          Animation: [NAME]      </floater.string> -    <text -     type="string" -     length="1" -     follows="left|top" -     font="SansSerif" -     height="19" -     layout="topleft" -     left="10" -     name="desc txt" -     top="25" -     width="80"> -        Description: -    </text> -    <line_editor -     border_style="line" -     border_thickness="1" -     follows="left|top|right" -     font="SansSerifSmall" -     height="19" -     layout="topleft" -     left_delta="95" -     max_length_bytes="127" -     name="desc" -     top="19" -     width="170" />      <button       height="20"       label="Play Inworld"       label_selected="Stop" +     follows="left|top"       layout="topleft"       left="10"       name="Inworld"       tool_tip="Play this animation so that others can see it" -     top="47" +     top="25"       width="125">         <button.commit_callback          function="PreviewAnim.Play"          parameter="Inworld" />       </button> +    <text +     type="string" +     length="1" +     follows="left|top" +     font="SansSerif" +     height="19" +     layout="topleft" +     left_pad="10" +     name="desc inworld" +     top_delta="3" +     width="160"> +        Other people can see +    </text>      <button       height="20"       label="Play Locally"       label_selected="Stop" +     follows="left|top"       layout="topleft" -     left_pad="5" +     left="10"       name="Locally"       tool_tip="Play this animation so that only you can see it" -     top_delta="0" +     top_pad="5"       width="125">         <button.commit_callback          function="PreviewAnim.Play"          parameter="Locally" />       </button> +    <text +     type="string" +     length="1" +     follows="left|top" +     font="SansSerif" +     height="19" +     layout="topleft" +     left_pad="10" +     name="desc local" +     top_delta="3" +     width="160"> +        Only you can see +    </text> +    <text +     type="string" +     length="1" +     follows="left|top" +     font="SansSerif" +     height="19" +     layout="topleft" +     left="10" +     name="desc txt" +     top_pad="7" +     width="80"> +        Description: +    </text> +    <line_editor +     border_style="line" +     border_thickness="1" +     follows="left|top|right" +     font="SansSerifSmall" +     height="19" +     layout="topleft" +     left="10" +     right="-10" +     max_length_bytes="127" +     name="desc" +     top_pad="0" /> +    <text +     type="string" +     length="1" +     follows="left|top" +     font="SansSerif" +     height="19" +     layout="topleft" +     left="10" +     name="adv_trigger" +     top_pad="7" +     width="100" +     text_color="EmphasisColor"> +        Advanced +    </text> +    <text +     type="string" +     length="1" +     follows="left|top" +     font="SansSerif" +     height="91" +     layout="topleft" +     left="10" +     name="AdvancedStats" +     top_pad="3" +     width="200"> +Priority: [PRIORITY] +Duration: [DURATION]s +Ease In: [EASE_IN]s +Ease Out: [EASE_OUT]s +Loop: [IS_LOOP] +Joints: [NUM_JOINTS] +    </text>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml b/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml index 35d4385487..2abd8ec5c0 100644 --- a/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml @@ -36,16 +36,14 @@                    stat="FramePixelDifference"                    bar_max="100"                    tick_spacing="10" -                  unit_scale="100" -                  precision="0"/> +                  unit_scale="100"/>          <stat_bar name="bandwidth"                    label="UDP Data Received"                    orientation="horizontal"                    unit_label="kbps"                    stat="activemessagedatareceived"                    bar_max="5000" -                  tick_spacing="500" -                  precision="0"/> +                  tick_spacing="500"/>  			  <stat_bar name="packet_loss"                    label="Packet Loss"                    orientation="horizontal" @@ -53,9 +51,7 @@                    stat="packetslostpercentstat"                    bar_max="5"                    tick_spacing="0.5" -                  precision="3" -                  show_bar="false" -                  show_mean="true"/> +                  show_bar="false"/>  		  </stat_view>  <!--Advanced Section-->        <stat_view name="advanced" @@ -73,7 +69,6 @@                      stat="numobjectsstat"                      bar_max="50000"                      tick_spacing="5000" -                    precision="0"                      show_bar="false"/>            <stat_bar name="newobjs"                      label="New Objects" @@ -109,12 +104,48 @@            <stat_bar name="texture_cache_read_latency"                      label="Cache Read Latency"                      orientation="horizontal" -                    unit_label="msec" +                    unit_label="sec"                      stat="texture_cache_read_latency"                      bar_max="1000.f"                      tick_spacing="100"                      show_history="true"                      show_bar="false"/> +          <stat_bar name="texture_decode_latency" +                    label="Cache Decode Latency" +                    orientation="horizontal" +                    unit_label="sec" +                    stat="texture_decode_latency" +                    bar_max="1000.f" +                    tick_spacing="100" +                    show_history="true" +                    show_bar="false"/> +          <stat_bar name="texture_decode_latency" +                    label="Cache Write Latency" +                    orientation="horizontal" +                    unit_label="sec" +                    stat="texture_write_latency" +                    bar_max="1000.f" +                    tick_spacing="100" +                    show_history="true" +                    show_bar="false"/> +          <stat_bar name="texture_fetch_latency" +                    label="Cache Fetch Latency" +                    orientation="horizontal" +                    unit_label="sec" +                    stat="texture_fetch_latency" +                    bar_max="1000.f" +                    tick_spacing="100" +                    show_history="true" +                    show_bar="false"/> +          <stat_bar name="texture_fetch_time" +                    label="Cache Fetch Time" +                    orientation="horizontal" +                    unit_label="sec" +                    stat="texture_fetch_time" +                    bar_max="1000.f" +                    tick_spacing="100" +                    show_history="true" +                    show_bar="false"/>            <stat_bar name="numimagesstat"                      label="Count"                      orientation="horizontal" @@ -142,7 +173,6 @@                      unit_label="/sec"                       bar_max="1024.f"                       tick_spacing="128.f" -                    precision="1"                      show_bar="false"/>  			    <stat_bar name="packetsoutstat"                      label="Packets Out" @@ -151,7 +181,6 @@                      unit_label="/sec"                        bar_max="1024.f"                       tick_spacing="128.f" -                    precision="1"                      show_bar="false"/>  			    <stat_bar name="objectdatareceived"                      label="Objects" @@ -160,7 +189,6 @@                      unit_label="kbps"                      bar_max="1024.f"                      tick_spacing="128.f" -                    precision="1"                      show_bar="false"/>  			    <stat_bar name="texturedatareceived"                      label="Texture" @@ -169,7 +197,6 @@                      unit_label="kbps"                      bar_max="1024.f"                      tick_spacing="128.f" -                    precision="1"                      show_bar="false"/>  			    <stat_bar name="assetudpdatareceived"                      label="Asset" @@ -178,7 +205,6 @@                      unit_label="kbps"                      bar_max="1024.f"                      tick_spacing="128.f" -                    precision="1"                      show_bar="false"/>  			    <stat_bar name="layersdatareceived"                      label="Layers" @@ -187,7 +213,6 @@                      unit_label="kbps"                      bar_max="1024.f"                      tick_spacing="128.f" -                    precision="1"                      show_bar="false"/>  			    <stat_bar name="messagedatain"                      label="Actual In" @@ -196,7 +221,6 @@                      unit_label="kbps"                      bar_max="1024.f"                      tick_spacing="128.f" -                    precision="1"                      show_bar="false"/>  			    <stat_bar name="messagedataout"                      label="Actual Out" @@ -205,7 +229,6 @@                      unit_label="kbps"                      bar_max="1024.f"                      tick_spacing="128.f" -                    precision="1"                      show_bar="false"/>  			  </stat_view>  		  </stat_view> @@ -218,77 +241,61 @@                    label="Objects"                    orientation="horizontal"                    stat="simobjects" -                  precision="0"                    bar_max="30000.f"                     tick_spacing="5000.f" -                  show_bar="false" -                  show_mean="false"/> +                  show_bar="false"/>  			  <stat_bar name="simactiveobjects"                    label="Active Objects"                    orientation="horizontal"                    stat="simactiveobjects" -                  precision="0"                    bar_max="5000.f"                     tick_spacing="750.f" -                  show_bar="false" -                  show_mean="false"/> +                  show_bar="false"/>  			  <stat_bar name="simactivescripts"                    label="Active Scripts"                    orientation="horizontal"                    stat="simactivescripts" -                  precision="0"                    bar_max="15000.f"                     tick_spacing="1875.f" -                  show_bar="false" -                  show_mean="false"/> +                  show_bar="false"/>  			  <stat_bar name="siminpps"                    label="Packets In"                    orientation="horizontal"                    stat="siminpps"                    unit_label="pps" -                  precision="0"                    bar_max="2000.f"                     tick_spacing="250.f" -                  show_bar="false" -                  show_mean="false"/> +                  show_bar="false"/>  			  <stat_bar name="simoutpps"                    label="Packets Out"                    orientation="horizontal"                    stat="simoutpps"                    unit_label="pps"  -                  precision="0"                    bar_max="2000.f"                     tick_spacing="250.f" -                  show_bar="false" -                  show_mean="false"/> +                  show_bar="false"/>  			  <stat_bar name="simpendingdownloads"                    label="Pending Downloads"                    orientation="horizontal"                    stat="simpendingdownloads" -                  precision="0"                    bar_max="800.f"                     tick_spacing="100.f" -                  show_bar="false" -                  show_mean="false"/> +                  show_bar="false"/>  			  <stat_bar name="simpendinguploads"                    label="Pending Uploads"                    orientation="horizontal"                    stat="simpendinguploads" -                  precision="0"                    bar_max="100.f"                     tick_spacing="25.f" -                  show_bar="false" -                  show_mean="false"/> +                  show_bar="false"/>  			  <stat_bar name="simtotalunackedbytes"                    label="Total Unacked Bytes"                    orientation="horizontal"                    stat="simtotalunackedbytes"                    unit_label="kb" -                  precision="1"                    bar_max="100000.f"                     tick_spacing="25000.f" -                  show_bar="false" -                  show_mean="false"/> +                  show_bar="false"/>  			  <stat_view name="simperf"                     label="Time (ms)"                     show_label="true"> @@ -297,81 +304,65 @@                      orientation="horizontal"                      stat="simframemsec"                      unit_label="ms" -                    precision="3"                      bar_max="40.f"                       tick_spacing="10.f" -                    show_bar="false" -                    show_mean="false"/> +                    show_bar="false"/>  			    <stat_bar name="simnetmsec"                      label="Net Time"                      orientation="horizontal"                      stat="simnetmsec"                      unit_label="ms" -                    precision="3"                      bar_max="40.f"                       tick_spacing="10.f" -                    show_bar="false" -                    show_mean="false"/> +                    show_bar="false"/>  			    <stat_bar name="simsimphysicsmsec"                      label="Physics Time"                      orientation="horizontal"                      stat="simsimphysicsmsec"                      unit_label="ms" -                    precision="3"                      bar_max="40.f"                       tick_spacing="10.f" -                    show_bar="false" -                    show_mean="false"/> +                    show_bar="false"/>  			    <stat_bar name="simsimothermsec"                      label="Simulation Time"                      orientation="horizontal"                      stat="simsimothermsec"                      unit_label="ms" -                    precision="3"                      bar_max="40.f"                       tick_spacing="10.f" -                    show_bar="false" -                    show_mean="false"/> +                    show_bar="false"/>  			    <stat_bar name="simagentmsec"                      label="Agent Time"                      orientation="horizontal"                      stat="simagentmsec"                      unit_label="ms" -                    precision="3" -                    bar_max="40.f"  +                     bar_max="40.f"                       tick_spacing="10.f" -                    show_bar="false" -                    show_mean="false"/> +                    show_bar="false"/>  			    <stat_bar name="simimagesmsec"                      label="Images Time"                      orientation="horizontal"                      stat="simimagesmsec"                      unit_label="ms" -                    precision="3"                      bar_max="40.f"                       tick_spacing="10.f" -                    show_bar="false" -                    show_mean="false"/> +                    show_bar="false"/>  			    <stat_bar name="simscriptmsec"                      label="Script Time"                      orientation="horizontal"                      stat="simscriptmsec"                      unit_label="ms" -                    precision="3"                      bar_max="40.f"                       tick_spacing="10.f" -                    show_bar="false" -                    show_mean="false"/> +                    show_bar="false"/>            <stat_bar name="simsparemsec"                      label="Spare Time"                      orientation="horizontal"                      stat="simsparemsec"                      unit_label="ms" -                    precision="3"                      bar_max="40.f"                      tick_spacing="10.f" -                    show_bar="false" -                    show_mean="false"/> +                    show_bar="false"/>  <!--2nd level time blocks under 'Details' second-->            <stat_view name="timedetails"                       label="Time Details (ms)" @@ -381,51 +372,41 @@                        orientation="horizontal"                        stat="simsimphysicsstepmsec"                        unit_label="ms" -                      precision="3"                        bar_max="40.f"                        tick_spacing="10.f" -                      show_bar="false" -                      show_mean="false"/> +                      show_bar="false"/>              <stat_bar name="simsimphysicsshapeupdatemsec"                        label="  Update Phys Shapes"                        orientation="horizontal"                        stat="simsimphysicsshapeupdatemsec"                        unit_label="ms" -                      precision="3" -                      bar_max="40.f" +                        bar_max="40.f"                        tick_spacing="10.f" -                      show_bar="false" -                      show_mean="false"/> +                      show_bar="false"/>              <stat_bar name="simsimphysicsothermsec"                        label="  Physics Other"                        orientation="horizontal"                        stat="simsimphysicsothermsec"                        unit_label="ms" -                      precision="3"                        bar_max="40.f"                        tick_spacing="10.f" -                      show_bar="false" -                      show_mean="false"/> +                      show_bar="false"/>              <stat_bar name="simsleepmsec"                        label="  Sleep Time"                        orientation="horizontal"                        stat="simsleepmsec"                        unit_label="ms" -                      precision="3"                        bar_max="40.f"                        tick_spacing="10.f" -                      show_bar="false" -                      show_mean="false"/> +                      show_bar="false"/>              <stat_bar name="simpumpiomsec"                        label="  Pump IO"                        orientation="horizontal"                        stat="simpumpiomsec"                        unit_label="ms" -                      precision="3"                        bar_max="40.f"                        tick_spacing="10.f" -                      show_bar="false" -                      show_mean="false"/> +                      show_bar="false"/>            </stat_view>  			  </stat_view>  		  </stat_view> diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml index 48d9eee4cd..998948fca1 100644 --- a/indra/newview/skins/default/xui/en/floater_select_key.xml +++ b/indra/newview/skins/default/xui/en/floater_select_key.xml @@ -33,7 +33,7 @@ Combination [KEYSTR] is reserved by menu.       height="30"       layout="topleft"       left="30" -     name="descritption" +     name="description"       top="25"       word_wrap="true"       width="212"> 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 index 1ea256b8b3..9278a1a598 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml @@ -319,6 +319,18 @@    </button>    <button     follows="left|top" +   height="22" +   label="Reset Fetching Time" +   layout="topleft" +   left_pad="175" +   name="reset_time_btn" +   top_delta="0" +   width="120"> +    <button.commit_callback +		function="TexFetchDebugger.ResetFetchTime" /> +  </button> +  <button +   follows="left|top"     height="20"     label="Cache Read"     layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 4420300a73..911ae483fb 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -703,8 +703,7 @@               function="Floater.Visible"               parameter="search" />              <menu_item_check.on_click -             function="Floater.Toggle" -             parameter="search" /> +             function="Avatar.ToggleSearch"/>              </menu_item_check>          <menu_item_separator/>          <menu_item_call @@ -774,7 +773,7 @@               label="My land holdings..."               name="My Land">              <menu_item_call.on_click -             function="Floater.Show" +             function="Floater.ShowOrBringToFront"               parameter="land_holdings" />        </menu_item_call>          <menu_item_call @@ -3909,6 +3908,12 @@ function="World.EnvPreset"              <menu_item_call.on_click               function="Advanced.CompressImage" />          </menu_item_call> +      <menu_item_call +       label="Compress File Test" +       name="Compress File Test"> +        <menu_item_call.on_click +         function="Advanced.CompressFileTest" /> +      </menu_item_call>        <menu_item_call           label="Enable Visual Leak Detector" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e01865a5ea..7be0e0ad85 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -214,6 +214,19 @@ Make sure your Internet connection is working properly.    <notification     icon="alertmodal.tga" +   name="LoginFailedToParse" +   type="alertmodal"> +    <tag>fail</tag> +Viewer received malformed response from server. Please, make sure your Internet connection is working properly and try again later. + +If you feel this is in error, please contact Support. +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga"     name="MessageTemplateNotFound"     type="alertmodal">  Message Template [PATH] not found. @@ -2984,6 +2997,14 @@ Darn. You have been logged out of [SECOND_LIFE].    <notification     icon="alertmodal.tga" +   name="InventoryUnusable" +   type="alertmodal"> +There was a problem loading your inventory. First, try logging out and logging in again. If you see this message again, contact Support to correct the problem. +    <tag>fail</tag> +  </notification> + +  <notification +   icon="alertmodal.tga"     name="OnlyOfficerCanBuyLand"     type="alertmodal">  Unable to buy land for the group: @@ -8800,6 +8821,13 @@ See SecondLife.log for details      type="alert">      Error while requesting mesh upload permissons.    </notification> + +  <notification +    name="MeshUploadProfilerError" +    icon="alert.tga" +    type="alert"> +Mesh uploader is incompatible with RenderGLCoreProfile, please turn RenderGLCoreProfile off in debug settings and restart the viewer. +  </notification>    <notification      name="RegionCapabilityRequestError" @@ -11812,5 +11840,15 @@ Unable to load the track into [TRACK].  Unable to load the track from [TRACK1] into [TRACK2].    <tag>fail</tag>    </notification> + +  <notification +   icon="alertmodal.tga" +   name="CompressionTestResults" +   type="alertmodal"> +Test result for gzip level 6 file compression with [FILE] of size [SIZE] KB: +Packing: [PACK_TIME]s [PSIZE]KB +Unpacking: [UNPACK_TIME]s [USIZE]KB +    <tag>fail</tag> +  </notification>  </notifications> diff --git a/indra/newview/skins/default/xui/en/panel_group_creation_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_creation_sidetray.xml index c0265c2fa2..466fb91dd0 100644 --- a/indra/newview/skins/default/xui/en/panel_group_creation_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_creation_sidetray.xml @@ -307,7 +307,7 @@ background_visible="true"          top_pad="8"          word_wrap="true"          halign="center"> -        Note: After 7 days, a group with no members (other than the creator) is deleted +        Note: Any group that has less than two members for 48 hours is automatically disbanded        </text>      </layout_panel>    </layout_stack> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index dff6f6e600..5e41ba4ae1 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -227,23 +227,25 @@       height="10"       layout="topleft"       left="30" -     name="Proxy Settings 1" -     mouse_opaque="false" -     top_pad="10" -     width="300"> -    Proxy Settings: -  </text> -  <text -     type="string" -     length="1" -     follows="left|top" -     height="10" -     layout="topleft" -     left="80" -     name="Proxy Settings 2" +     name="Proxy Settings:"       mouse_opaque="false"       top_pad="5"       width="300"> -    Your system's existing proxy settings will be used +    Proxy Settings:    </text> +  <button +	label="Adjust proxy settings" +    follows="left|top" +    height="23" +	width="140" +    label_selected="Browse" +    layout="topleft" +    left_delta="50" +    name="set_proxy" +    top_pad="5" +    > +    <button.commit_callback +		  function="Pref.Proxy" /> +  </button>  </panel> + diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml index 898e92e030..d1cfb8ead6 100644 --- a/indra/newview/skins/default/xui/en/panel_region_general.xml +++ b/indra/newview/skins/default/xui/en/panel_region_general.xml @@ -51,7 +51,7 @@       left_delta="50"       name="version_channel_text"       top_delta="0" -     width="225"> +     width="400">          unknown      </text>      <text diff --git a/indra/newview/skins/default/xui/es/floater_buy_contents.xml b/indra/newview/skins/default/xui/es/floater_buy_contents.xml index 3563d4bd0f..d078868db2 100644 --- a/indra/newview/skins/default/xui/es/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/es/floater_buy_contents.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <floater name="floater_buy_contents" title="COMPRAR LOS CONTENIDOS">  	<text name="contains_text"> -		<nolink>[NOMBRE]</nolink> contiene: +		<nolink>[NAME]</nolink> contiene:  	</text>  	<text name="buy_text">  		¿Comprar por [AMOUNT] L$ a [NAME]? diff --git a/indra/newview/skins/default/xui/es/floater_import_collada.xml b/indra/newview/skins/default/xui/es/floater_import_collada.xml index 7e9a00797a..24df8e41a3 100644 --- a/indra/newview/skins/default/xui/es/floater_import_collada.xml +++ b/indra/newview/skins/default/xui/es/floater_import_collada.xml @@ -1,13 +1,13 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <floater name="Import Collada" title="Importar escena">  	<text name="mesh count"> -		Redes: [RECUENTO] +		Redes: [COUNT]  	</text>  	<text name="texture count"> -		Texturas: [RECUENTO] +		Texturas: [COUNT]  	</text>  	<text name="status"> -		Estado: [ESTADO] +		Estado: [STATUS]  	</text>  	<button label="Cancelar" name="cancel"/>  	<button label="OK" name="ok"/> @@ -15,9 +15,9 @@  		Inactivo  	</string>  	<string name="status_uploading"> -		Cargando [NOMBRE] +		Cargando [NAME]  	</string>  	<string name="status_creating"> -		Creando objeto [NOMBRE] +		Creando objeto [NAME]  	</string>  </floater> diff --git a/indra/newview/skins/default/xui/es/menu_place_add_button.xml b/indra/newview/skins/default/xui/es/menu_place_add_button.xml index 4b2f908a06..2032b9add9 100644 --- a/indra/newview/skins/default/xui/es/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/es/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Añadir una carpeta" name="add_folder"/>  	<menu_item_call label="Añadir este hito" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/es/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/es/menu_teleport_history_item.xml index 1ff555b727..d54cd65478 100644 --- a/indra/newview/skins/default/xui/es/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/es/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Teleportar" name="Teleport"/>  	<menu_item_call label="Más información" name="More Information"/>  	<menu_item_call label="Copiar la SLurl" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index c7750320d5..54707116d4 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -3389,15 +3389,15 @@ Con los siguientes Residentes:  		Error de transferencia a grupo.  	</notification>  	<notification name="ReleaseLandThrottled"> -		La parcela [NOMBRE_PARCELA] no se puede abandonar en este momento. +		La parcela [PARCEL_NAME] no se puede abandonar en este momento.  	</notification>  	<notification name="ReleasedLandWithReclaim"> -		Ya está disponible la parcela [NOMBRE_PARCELA] de [ÁREA] m². +		Ya está disponible la parcela [PARCEL_NAME] de [AREA] m². -Dispondrás de [PERÍODO_DE_RECLAMACIÓN] horas para reclamar la cantidad de 0 L$ antes de que se ponga en venta. +Dispondrás de [RECLAIM_PERIOD] horas para reclamar la cantidad de 0 L$ antes de que se ponga en venta.  	</notification>  	<notification name="ReleasedLandNoReclaim"> -		Ya está disponible la parcela [NOMBRE_PARCELA] de [ÁREA] m². +		Ya está disponible la parcela [PARCEL_NAME] de [AREA] m².  Ya está en venta.  	</notification> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index ebb4ceaa7e..e5598978ce 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -204,10 +204,10 @@ Si deseas obtener más información, consulta las preguntas frecuentes que apare  http://secondlife.com/viewer-access-faq  	</string>  	<string name="LoginIntermediateOptionalUpdateAvailable"> -		Actualización opcional del visor disponible: [VERSIÓN] +		Actualización opcional del visor disponible: [VERSION]  	</string>  	<string name="LoginFailedRequiredUpdate"> -		Actualización necesaria del visor: [VERSIÓN] +		Actualización necesaria del visor: [VERSION]  	</string>  	<string name="LoginFailedAlreadyLoggedIn">  		El agente ya ha iniciado sesión. @@ -248,7 +248,7 @@ support@secondlife.com.  	</string>  	<string name="LoginFailedAcountSuspended">  		No se podrá acceder a tu cuenta hasta las -[HORA] (horario de la costa del Pacífico). +[TIME] (horario de la costa del Pacífico).  	</string>  	<string name="LoginFailedAccountDisabled">  		En este momento no podemos completar la solicitud.  @@ -261,7 +261,7 @@ Ponte en contacto con support@secondlife.com.  	<string name="LoginFailedAccountMaintenance">  		Se están realizando tareas rutinarias de mantenimiento en tu cuenta.  No se podrá acceder a tu cuenta hasta las -[HORA] (horario de la costa del Pacífico). +[TIME] (horario de la costa del Pacífico).  Si crees que se trata de un error, ponte en contacto con support@secondlife.com.  	</string>  	<string name="LoginFailedPendingLogoutFault"> @@ -279,7 +279,7 @@ Por favor, aguarda un momento antes de intentar conectarte nuevamente.  	</string>  	<string name="LoginFailedRestrictedHours">  		Tu cuenta solo puede acceder a Second Life -entre las [INICIO] y las [FIN] (horario de la costa del Pacífico). +entre las [START] y las [END] (horario de la costa del Pacífico).  Inténtalo de nuevo durante ese horario.  Si crees que se trata de un error, ponte en contacto con support@secondlife.com.  	</string> diff --git a/indra/newview/skins/default/xui/fr/menu_place_add_button.xml b/indra/newview/skins/default/xui/fr/menu_place_add_button.xml index 92f9e7719d..4bae34beaa 100644 --- a/indra/newview/skins/default/xui/fr/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/fr/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Ajouter un dossier" name="add_folder"/>  	<menu_item_call label="Ajouter un repère" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/fr/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/fr/menu_teleport_history_item.xml index ba8ed9b3f8..ef864029ba 100644 --- a/indra/newview/skins/default/xui/fr/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/fr/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Téléporter" name="Teleport"/>  	<menu_item_call label="Plus d'informations" name="More Information"/>  	<menu_item_call label="Copier la SLurl" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/it/menu_place_add_button.xml b/indra/newview/skins/default/xui/it/menu_place_add_button.xml index 0e783c0000..abdc0ea794 100644 --- a/indra/newview/skins/default/xui/it/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/it/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Aggiungi cartella" name="add_folder"/>  	<menu_item_call label="Aggiungi punto di riferimento" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/it/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/it/menu_teleport_history_item.xml index 31236895fa..f7da322006 100644 --- a/indra/newview/skins/default/xui/it/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/it/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Teleport" name="Teleport"/>  	<menu_item_call label="Maggiori informazioni" name="More Information"/>  	<menu_item_call label="Copia SLurl" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ja/menu_place_add_button.xml b/indra/newview/skins/default/xui/ja/menu_place_add_button.xml index d5ce88b055..d19bc44451 100644 --- a/indra/newview/skins/default/xui/ja/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/ja/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="フォルダを追加" name="add_folder"/>  	<menu_item_call label="ランドマークを追加" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ja/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/ja/menu_teleport_history_item.xml index 61642048b8..1cc230e5b6 100644 --- a/indra/newview/skins/default/xui/ja/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/ja/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="テレポート" name="Teleport"/>  	<menu_item_call label="もっと詳しく" name="More Information"/>  	<menu_item_call label="SLurl をコピー" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_place_add_button.xml b/indra/newview/skins/default/xui/pl/menu_place_add_button.xml index ff19f32ba8..107d4fae3a 100644 --- a/indra/newview/skins/default/xui/pl/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/pl/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Dodaj folder" name="add_folder" />  	<menu_item_call label="Dodaj do Landmarków" name="add_landmark" /> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pl/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/pl/menu_teleport_history_item.xml index 7d8519324f..0ed1d510eb 100644 --- a/indra/newview/skins/default/xui/pl/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/pl/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Teleportuj" name="Teleport" />  	<menu_item_call label="Więcej szczegółów" name="More Information" />  	<menu_item_call label="Kopiuj SLurl do schowka" name="CopyToClipboard" /> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_place_add_button.xml b/indra/newview/skins/default/xui/pt/menu_place_add_button.xml index d099d04f8d..89a634d12f 100644 --- a/indra/newview/skins/default/xui/pt/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/pt/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Adicionar pasta" name="add_folder"/>  	<menu_item_call label="Adicionar marco" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/pt/menu_teleport_history_item.xml index 3a2b3a8847..db759cb4e3 100644 --- a/indra/newview/skins/default/xui/pt/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/pt/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Teletransportar" name="Teleport"/>  	<menu_item_call label="Mais informações" name="More Information"/>  	<menu_item_call label="Copiar SLurl" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ru/menu_place_add_button.xml b/indra/newview/skins/default/xui/ru/menu_place_add_button.xml index b1a38fb9eb..9298c032d5 100644 --- a/indra/newview/skins/default/xui/ru/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/ru/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Добавить папку" name="add_folder"/>  	<menu_item_call label="Добавить закладку" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ru/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/ru/menu_teleport_history_item.xml index f495d27bf3..84a76ae0e0 100644 --- a/indra/newview/skins/default/xui/ru/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/ru/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Телепорт" name="Teleport"/>  	<menu_item_call label="Информация" name="More Information"/>  	<menu_item_call label="Копировать URL SL" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/tr/menu_place_add_button.xml b/indra/newview/skins/default/xui/tr/menu_place_add_button.xml index 8e52b3f7f2..69bc265823 100644 --- a/indra/newview/skins/default/xui/tr/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/tr/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="Klasör Ekle" name="add_folder"/>  	<menu_item_call label="Yer İmi Ekle" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/tr/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/tr/menu_teleport_history_item.xml index d7ff807c3d..59ba134965 100644 --- a/indra/newview/skins/default/xui/tr/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/tr/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="Işınla" name="Teleport"/>  	<menu_item_call label="Ek Bilgi" name="More Information"/>  	<menu_item_call label="SLurl'i Kopyala" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_place_add_button.xml b/indra/newview/skins/default/xui/zh/menu_place_add_button.xml index 95f8917234..165e2b6f08 100644 --- a/indra/newview/skins/default/xui/zh/menu_place_add_button.xml +++ b/indra/newview/skins/default/xui/zh/menu_place_add_button.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<menu name="menu_folder_gear"> +<toggleable_menu name="menu_create">  	<menu_item_call label="添加資料夾" name="add_folder"/>  	<menu_item_call label="添加地標" name="add_landmark"/> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/zh/menu_teleport_history_item.xml index bf60983896..200e1904f6 100644 --- a/indra/newview/skins/default/xui/zh/menu_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/zh/menu_teleport_history_item.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<context_menu name="Teleport History Item Context Menu"> +<toggleable_menu name="Teleport History Item Menu">  	<menu_item_call label="瞬間傳送" name="Teleport"/>  	<menu_item_call label="更多資訊" name="More Information"/>  	<menu_item_call label="覆製 SLurl" name="CopyToClipboard"/> -</context_menu> +</toggleable_menu> diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py index cff40aa4c2..365848b819 100755 --- a/indra/newview/tests/test_llxmlrpc_peer.py +++ b/indra/newview/tests/test_llxmlrpc_peer.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3  """\  @file   test_llxmlrpc_peer.py  @author Nat Goodspeed @@ -31,7 +31,7 @@ $/LicenseInfo$  import os  import sys -from SimpleXMLRPCServer import SimpleXMLRPCServer +from xmlrpc.server import SimpleXMLRPCServer  mydir = os.path.dirname(__file__)       # expected to be .../indra/newview/tests/  sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests")) @@ -85,7 +85,7 @@ if __name__ == "__main__":          # "Then there's Windows"          # Instantiate a TestServer on the first free port in the specified          # port range. -        xmlrpcd, port = freeport(xrange(8000, 8020), make_server) +        xmlrpcd, port = freeport(range(8000, 8020), make_server)      # Pass the selected port number to the subject test program via the      # environment. We don't want to impose requirements on the test program's diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 52401c736d..c7e49206c8 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3  """\  @file viewer_manifest.py  @author Ryan Williams @@ -27,6 +27,8 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA  $/LicenseInfo$  """  import errno +import glob +import itertools  import json  import os  import os.path @@ -75,7 +77,7 @@ class ViewerManifest(LLManifest):                  # include the extracted list of contributors                  contributions_path = "../../doc/contributions.txt"                  contributor_names = self.extract_names(contributions_path) -                self.put_in_file(contributor_names, "contributors.txt", src=contributions_path) +                self.put_in_file(contributor_names.encode(), "contributors.txt", src=contributions_path)                  # ... and the default camera position settings                  self.path("camera") @@ -114,17 +116,17 @@ class ViewerManifest(LLManifest):                  if sourceid:                      settings_install['sourceid'] = settings_template['sourceid'].copy()                      settings_install['sourceid']['Value'] = sourceid -                    print "Set sourceid in settings_install.xml to '%s'" % sourceid +                    print("Set sourceid in settings_install.xml to '%s'" % sourceid)                  if self.args.get('channel_suffix'):                      settings_install['CmdLineChannel'] = settings_template['CmdLineChannel'].copy()                      settings_install['CmdLineChannel']['Value'] = self.channel_with_pkg_suffix() -                    print "Set CmdLineChannel in settings_install.xml to '%s'" % self.channel_with_pkg_suffix() +                    print("Set CmdLineChannel in settings_install.xml to '%s'" % self.channel_with_pkg_suffix())                  if self.args.get('grid'):                      settings_install['CmdLineGridChoice'] = settings_template['CmdLineGridChoice'].copy()                      settings_install['CmdLineGridChoice']['Value'] = self.grid() -                    print "Set CmdLineGridChoice in settings_install.xml to '%s'" % self.grid() +                    print("Set CmdLineGridChoice in settings_install.xml to '%s'" % self.grid())                  # put_in_file(src=) need not be an actual pathname; it                  # only needs to be non-empty @@ -184,7 +186,7 @@ class ViewerManifest(LLManifest):              #we likely no longer need the test, since we will throw an exception above, but belt and suspenders and we get the              #return code for free.              if not self.path2basename(os.pardir, "build_data.json"): -                print "No build_data.json file" +                print("No build_data.json file")      def finish_build_data_dict(self, build_data_dict):          return build_data_dict @@ -263,13 +265,13 @@ class ViewerManifest(LLManifest):          return "icons/" + self.channel_type()      def extract_names(self,src): +        """Extract contributor names from source file, returns string"""          try: -            contrib_file = open(src,'r') +            with open(src, 'r') as contrib_file:  +                lines = contrib_file.readlines()          except IOError: -            print "Failed to open '%s'" % src +            print("Failed to open '%s'" % src)              raise -        lines = contrib_file.readlines() -        contrib_file.close()          # All lines up to and including the first blank line are the file header; skip them          lines.reverse() # so that pop will pull from first to last line @@ -305,7 +307,7 @@ class ViewerManifest(LLManifest):          """          Like ln -sf, but uses os.symlink() instead of running ln. This creates          a symlink at 'dst' that points to 'src' -- see: -        https://docs.python.org/2/library/os.html#os.symlink +        https://docs.python.org/3/library/os.html#os.symlink          If you omit 'dst', this creates a symlink with basename(src) at          get_dst_prefix() -- in other words: put a symlink to this pathname @@ -367,11 +369,11 @@ class ViewerManifest(LLManifest):                          os.remove(dst)                          os.symlink(src, dst)                  elif os.path.isdir(dst): -                    print "Requested symlink (%s) exists but is a directory; replacing" % dst +                    print("Requested symlink (%s) exists but is a directory; replacing" % dst)                      shutil.rmtree(dst)                      os.symlink(src, dst)                  elif os.path.exists(dst): -                    print "Requested symlink (%s) exists but is a file; replacing" % dst +                    print("Requested symlink (%s) exists but is a file; replacing" % dst)                      os.remove(dst)                      os.symlink(src, dst)                  else: @@ -379,8 +381,8 @@ class ViewerManifest(LLManifest):                      raise          except Exception as err:              # report -            print "Can't symlink %r -> %r: %s: %s" % \ -                  (dst, src, err.__class__.__name__, err) +            print("Can't symlink %r -> %r: %s: %s" % \ +                  (dst, src, err.__class__.__name__, err))              # if caller asked us not to catch, re-raise this exception              if not catch:                  raise @@ -441,7 +443,7 @@ class WindowsManifest(ViewerManifest):              else:                  raise Exception("Directories are not supported by test_CRT_and_copy_action()")          else: -            print "Doesn't exist:", src +            print("Doesn't exist:", src)      def test_for_no_msvcrt_manifest_and_copy_action(self, src, dst):          # This is used to test that no manifest for the msvcrt exists. @@ -470,7 +472,7 @@ class WindowsManifest(ViewerManifest):              else:                  raise Exception("Directories are not supported by test_CRT_and_copy_action()")          else: -            print "Doesn't exist:", src +            print("Doesn't exist:", src)      def construct(self):          super(WindowsManifest, self).construct() @@ -683,8 +685,7 @@ class WindowsManifest(ViewerManifest):          result = ""          dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])]          # sort deepest hierarchy first -        dest_files.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) -        dest_files.reverse() +        dest_files.sort(key=lambda f: (f.count(os.path.sep), f), reverse=True)          out_path = None          for pkg_file in dest_files:              rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,'')) @@ -707,8 +708,7 @@ class WindowsManifest(ViewerManifest):              for d in deleted_file_dirs:                  deleted_dirs.extend(path_ancestors(d))              # sort deepest hierarchy first -            deleted_dirs.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) -            deleted_dirs.reverse() +            deleted_dirs.sort(key=lambda f: (f.count(os.path.sep), f), reverse=True)              prev = None              for d in deleted_dirs:                  if d != prev:   # skip duplicates @@ -794,19 +794,19 @@ class WindowsManifest(ViewerManifest):          installer_created=False          nsis_attempts=3          nsis_retry_wait=15 -        for attempt in xrange(nsis_attempts): +        for attempt in range(nsis_attempts):              try:                  self.run_command([NSIS_path, '/V2', self.dst_path_of(tempfile)])              except ManifestError as err:                  if attempt+1 < nsis_attempts: -                    print >> sys.stderr, "nsis failed, waiting %d seconds before retrying" % nsis_retry_wait +                    print("nsis failed, waiting %d seconds before retrying" % nsis_retry_wait, file=sys.stderr)                      time.sleep(nsis_retry_wait)                      nsis_retry_wait*=2              else:                  # NSIS worked! Done!                  break          else: -            print >> sys.stderr, "Maximum nsis attempts exceeded; giving up" +            print("Maximum nsis attempts exceeded; giving up", file=sys.stderr)              raise          self.sign(installer_file) @@ -818,10 +818,10 @@ class WindowsManifest(ViewerManifest):          python  = os.environ.get('PYTHON', sys.executable)          if os.path.exists(sign_py):              dst_path = self.dst_path_of(exe) -            print "about to run signing of: ", dst_path +            print("about to run signing of: ", dst_path)              self.run_command([python, sign_py, dst_path])          else: -            print "Skipping code signing of %s %s: %s not found" % (self.dst_path_of(exe), exe, sign_py) +            print("Skipping code signing of %s %s: %s not found" % (self.dst_path_of(exe), exe, sign_py))      def escape_slashes(self, path):          return path.replace('\\', '\\\\\\\\') @@ -865,14 +865,15 @@ class DarwinManifest(ViewerManifest):              if bugsplat_db:                  # Inject BugsplatServerURL into Info.plist if provided.                  Info_plist = self.dst_path_of("Info.plist") -                Info = plistlib.readPlist(Info_plist) -                # https://www.bugsplat.com/docs/platforms/os-x#configuration -                Info["BugsplatServerURL"] = \ -                    "https://{}.bugsplat.com/".format(bugsplat_db) -                self.put_in_file( -                    plistlib.writePlistToString(Info), -                    os.path.basename(Info_plist), -                    "Info.plist") +                with open(Info_plist, 'rb') as f: +                    Info = plistlib.load(f) +                    # https://www.bugsplat.com/docs/platforms/os-x#configuration +                    Info["BugsplatServerURL"] = \ +                        "https://{}.bugsplat.com/".format(bugsplat_db) +                    self.put_in_file( +                        plistlib.dumps(Info), +                        os.path.basename(Info_plist), +                        "Info.plist")              # CEF framework goes inside Contents/Frameworks.              # Remember where we parked this car. @@ -998,10 +999,10 @@ class DarwinManifest(ViewerManifest):                          added = [os.path.relpath(d, self.get_dst_prefix())                                   for s, d in self.file_list[oldlen:]]                      except MissingError as err: -                        print >> sys.stderr, "Warning: "+err.msg +                        print("Warning: "+err.msg, file=sys.stderr)                          added = []                      if not added: -                        print "Skipping %s" % dst +                        print("Skipping %s" % dst)                      return added                  # dylibs is a list of all the .dylib files we expect to need @@ -1194,7 +1195,7 @@ class DarwinManifest(ViewerManifest):          # mount the image and get the name of the mount point and device node          try: -            hdi_output = subprocess.check_output(['hdiutil', 'attach', '-private', sparsename]) +            hdi_output = subprocess.check_output(['hdiutil', 'attach', '-private', sparsename], text=True)          except subprocess.CalledProcessError as err:              sys.exit("failed to mount image at '%s'" % sparsename) @@ -1219,11 +1220,11 @@ class DarwinManifest(ViewerManifest):              if not os.path.exists (self.src_path_of(dmg_template)):                  dmg_template = os.path.join ('installers', 'darwin', 'release-dmg') -            for s,d in {self.get_dst_prefix():app_name + ".app", +            for s,d in list({self.get_dst_prefix():app_name + ".app",                          os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns",                          os.path.join(dmg_template, "background.jpg"): "background.jpg", -                        os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items(): -                print "Copying to dmg", s, d +                        os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items()): +                print("Copying to dmg", s, d)                  self.copy_action(self.src_path_of(s), os.path.join(volpath, d))              # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit) @@ -1248,7 +1249,7 @@ class DarwinManifest(ViewerManifest):              # and invalidate the signatures.              if 'signature' in self.args:                  app_in_dmg=os.path.join(volpath,self.app_name()+".app") -                print "Attempting to sign '%s'" % app_in_dmg +                print("Attempting to sign '%s'" % app_in_dmg)                  identity = self.args['signature']                  if identity == '':                      identity = 'Developer ID Application' @@ -1264,47 +1265,79 @@ class DarwinManifest(ViewerManifest):                      keychain_pwd_path = os.path.join(build_secrets_checkout,'code-signing-osx','password.txt')                      keychain_pwd = open(keychain_pwd_path).read().rstrip() -                    # Note: As of macOS Sierra, keychains are created with names postfixed with '-db' so for example, the -                    #       SL Viewer keychain would by default be found in ~/Library/Keychains/viewer.keychain-db instead of -                    #       just ~/Library/Keychains/viewer.keychain in earlier versions. +                    # Note: As of macOS Sierra, keychains are created with +                    #       names postfixed with '-db' so for example, the SL +                    #       Viewer keychain would by default be found in +                    #       ~/Library/Keychains/viewer.keychain-db instead of +                    #       just ~/Library/Keychains/viewer.keychain in +                    #       earlier versions.                      # -                    #       Because we have old OS files from previous versions of macOS on the build hosts, the configurations -                    #       are different on each host. Some have viewer.keychain, some have viewer.keychain-db and some have both. -                    #       As you can see in the line below, this script expects the Linden Developer cert/keys to be in viewer.keychain. +                    #       Because we have old OS files from previous +                    #       versions of macOS on the build hosts, the +                    #       configurations are different on each host. Some +                    #       have viewer.keychain, some have viewer.keychain-db +                    #       and some have both. As you can see in the line +                    #       below, this script expects the Linden Developer +                    #       cert/keys to be in viewer.keychain.                      # -                    #       To correctly sign builds you need to make sure ~/Library/Keychains/viewer.keychain exists on the host -                    #       and that it contains the correct cert/key. If a build host is set up with a clean version of macOS Sierra (or later) -                    #       then you will need to change this line (and the one for 'codesign' command below) to point to right place or else -                    #       pull in the cert/key into the default viewer keychain 'viewer.keychain-db' and export it to 'viewer.keychain' +                    #       To correctly sign builds you need to make sure +                    #       ~/Library/Keychains/viewer.keychain exists on the +                    #       host and that it contains the correct cert/key. If +                    #       a build host is set up with a clean version of +                    #       macOS Sierra (or later) then you will need to +                    #       change this line (and the one for 'codesign' +                    #       command below) to point to right place or else +                    #       pull in the cert/key into the default viewer +                    #       keychain 'viewer.keychain-db' and export it to +                    #       'viewer.keychain'                      viewer_keychain = os.path.join(home_path, 'Library',                                                     'Keychains', 'viewer.keychain')                      self.run_command(['security', 'unlock-keychain',                                        '-p', keychain_pwd, viewer_keychain]) -                    signed=False -                    sign_attempts=3                      sign_retry_wait=15 -                    libvlc_path = app_in_dmg + "/Contents/Resources/llplugin/media_plugin_libvlc.dylib" -                    cef_path = app_in_dmg + "/Contents/Resources/llplugin/media_plugin_cef.dylib" -                    slplugin_path = app_in_dmg + "/Contents/Resources/SLPlugin.app/Contents/MacOS/SLPlugin" -                    greenlet_path = app_in_dmg + "/Contents/Resources/updater/greenlet/_greenlet.so" -                    while (not signed) and (sign_attempts > 0): +                    resources = app_in_dmg + "/Contents/Resources/" +                    plain_sign = glob.glob(resources + "llplugin/*.dylib") +                    deep_sign = [ +                        resources + "updater/SLVersionChecker", +                        resources + "SLPlugin.app/Contents/MacOS/SLPlugin", +                        app_in_dmg, +                        ] +                    for attempt in range(3): +                        if attempt: # second or subsequent iteration +                            print >> sys.stderr, \ +                                ("codesign failed, waiting %d seconds before retrying" % +                                 sign_retry_wait) +                            time.sleep(sign_retry_wait) +                            sign_retry_wait*=2 +                          try: -                            sign_attempts-=1                              # Note: See blurb above about names of keychains -                            self.run_command(['codesign', '--force', '--timestamp','--keychain', viewer_keychain, '--sign', identity, libvlc_path]) -                            self.run_command(['codesign', '--force', '--timestamp', '--keychain', viewer_keychain, '--sign', identity, cef_path]) -                            self.run_command(['codesign', '--force', '--timestamp', '--keychain', viewer_keychain, '--sign', identity, greenlet_path]) -                            self.run_command(['codesign', '--verbose', '--deep', '--force', '--entitlements', self.src_path_of("slplugin.entitlements"), '--options', 'runtime', '--keychain', viewer_keychain, '--sign', identity, slplugin_path]) -                            self.run_command(['codesign', '--verbose', '--deep', '--force', '--entitlements', self.src_path_of("slplugin.entitlements"), '--options', 'runtime', '--keychain', viewer_keychain, '--sign', identity, app_in_dmg]) -                            signed=True # if no exception was raised, the codesign worked +                            for signee in plain_sign: +                                self.run_command( +                                    ['codesign', +                                     '--force', +                                     '--timestamp', +                                     '--keychain', viewer_keychain, +                                     '--sign', identity, +                                     signee]) +                            for signee in deep_sign: +                                self.run_command( +                                    ['codesign', +                                     '--verbose', +                                     '--deep', +                                     '--force', +                                     '--entitlements', self.src_path_of("slplugin.entitlements"), +                                     '--options', 'runtime', +                                     '--keychain', viewer_keychain, +                                     '--sign', identity, +                                     signee]) +                            break # if no exception was raised, the codesign worked                          except ManifestError as err: -                            if sign_attempts: -                                print >> sys.stderr, "codesign failed, waiting %d seconds before retrying" % sign_retry_wait -                                time.sleep(sign_retry_wait) -                                sign_retry_wait*=2 -                            else: -                                print >> sys.stderr, "Maximum codesign attempts exceeded; giving up" -                                raise +                            # 'err' goes out of scope +                            sign_failed = err +                    else: +                        print >> sys.stderr, "Maximum codesign attempts exceeded; giving up" +                        raise sign_failed                      self.run_command(['spctl', '-a', '-texec', '-vvvv', app_in_dmg])                      self.run_command([self.src_path_of("installers/darwin/apple-notarize.sh"), app_in_dmg]) @@ -1312,7 +1345,7 @@ class DarwinManifest(ViewerManifest):              # Unmount the image even if exceptions from any of the above               self.run_command(['hdiutil', 'detach', '-force', devfile]) -        print "Converting temp disk image to final disk image" +        print("Converting temp disk image to final disk image")          self.run_command(['hdiutil', 'convert', sparsename, '-format', 'UDZO',                            '-imagekey', 'zlib-level=9', '-o', finalname])          # get rid of the temp file @@ -1369,7 +1402,7 @@ class LinuxManifest(ViewerManifest):          # Get the icons based on the channel type          icon_path = self.icon_path() -        print "DEBUG: icon_path '%s'" % icon_path +        print("DEBUG: icon_path '%s'" % icon_path)          with self.prefix(src=icon_path) :              self.path("secondlife_256.png","secondlife_icon.png")              with self.prefix(dst="res-sdl") : @@ -1390,7 +1423,7 @@ class LinuxManifest(ViewerManifest):          # llcommon          if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"): -            print "Skipping llcommon.so (assuming llcommon was linked statically)" +            print("Skipping llcommon.so (assuming llcommon was linked statically)")          self.path("featuretable_linux.txt") @@ -1425,14 +1458,14 @@ class LinuxManifest(ViewerManifest):                                    '--numeric-owner', '-cjf',                                   tempname + '.tar.bz2', installer_name])              else: -                print "Skipping %s.tar.bz2 for non-Release build (%s)" % \ -                      (installer_name, self.args['buildtype']) +                print("Skipping %s.tar.bz2 for non-Release build (%s)" % \ +                      (installer_name, self.args['buildtype']))          finally:              self.run_command(["mv", tempname, realname])      def strip_binaries(self):          if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): -            print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" +            print("* Going strip-crazy on the packaged binaries, since this is a RELEASE build")              # makes some small assumptions about our packaged dir structure              self.run_command(                  ["find"] + @@ -1498,7 +1531,7 @@ class Linux_i686_Manifest(LinuxManifest):                  self.path("libtcmalloc.so*") #formerly called google perf tools                  pass              except: -                print "tcmalloc files not found, skipping" +                print("tcmalloc files not found, skipping")                  pass              if self.args['fmodstudio'] == 'ON': @@ -1508,7 +1541,7 @@ class Linux_i686_Manifest(LinuxManifest):                      self.path("libfmod.so")                      pass                  except: -                    print "Skipping libfmod.so - not found" +                    print("Skipping libfmod.so - not found")                      pass          # Vivox runtimes @@ -1537,9 +1570,9 @@ class Linux_x86_64_Manifest(LinuxManifest):  if __name__ == "__main__":      # Report our own command line so that, in case of trouble, a developer can      # manually rerun the same command. -    print('%s \\\n%s' % +    print(('%s \\\n%s' %            (sys.executable, -           ' '.join((("'%s'" % arg) if ' ' in arg else arg) for arg in sys.argv))) +           ' '.join((("'%s'" % arg) if ' ' in arg else arg) for arg in sys.argv))))      # fmodstudio and openal can be used simultaneously and controled by environment      extra_arguments = [          dict(name='bugsplat', description="""BugSplat database to which to post crashes, | 
