diff options
Diffstat (limited to 'indra/newview')
76 files changed, 871 insertions, 674 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c2b1473e8f..c76145fab3 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -735,7 +735,6 @@ set(viewer_SOURCE_FILES llvovolume.cpp llvowater.cpp llvowlsky.cpp - llwatchdog.cpp llwearableitemslist.cpp llwearablelist.cpp llweb.cpp @@ -1412,7 +1411,6 @@ set(viewer_HEADER_FILES llvovolume.h llvowater.h llvowlsky.h - llwatchdog.h llwearableitemslist.h llwearablelist.h llweb.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 4703009f54..2aaedf9944 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -2026.01.0 +26.1.0 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5d82b38c2a..03b5259b75 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9102,7 +9102,7 @@ <key>Comment</key> <string>Show reflection probes in the transparency debug view</string> <key>Persist</key> - <integer>1</integer> + <integer>0</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> @@ -16607,5 +16607,16 @@ <key>Value</key> <integer>2</integer> </map> + <key>PurgeDiskCacheOnStartup</key> + <map> + <key>Comment</key> + <string>Whether or not to LRU purge the disk cache during startup on main thread</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> </map> </llsd> diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index dd9e883fdf..abe61fe892 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -146,6 +146,9 @@ vec3 srgb_to_linear(vec3 c); void main() { vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; + + basecolor.a *= vertex_color.a; + if (basecolor.a < minimum_alpha) { discard; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index e405a9ea2d..69c9e9ff84 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -51,9 +51,7 @@ in vec3 vary_norm; in vec4 vertex_color; //vertex color should be treated as sRGB #endif -#ifdef HAS_ALPHA_MASK uniform float minimum_alpha; -#endif uniform mat4 proj_mat; uniform mat4 inv_proj; @@ -225,6 +223,13 @@ void main() float final_alpha = diffuse_linear.a; +#ifdef IS_AVATAR_SKIN + if(final_alpha < minimum_alpha) + { + discard; + } +#endif + #ifdef USE_VERTEX_COLOR final_alpha *= vertex_color.a; diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 187876e3b8..c170672859 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -1027,6 +1027,12 @@ bool Image::prepImpl(Asset& asset, const LLUUID& id) std::string dir = gDirUtilp->getDirName(asset.mFilename); std::string img_file = dir + gDirUtilp->getDirDelimiter() + mUri; + if (!gDirUtilp->fileExists(img_file)) + { + // URI might be escaped, unescape. + img_file = dir + gDirUtilp->getDirDelimiter() + LLURI::unescape(mUri); + } + LLUUID tracking_id = LLLocalBitmapMgr::getInstance()->addUnit(img_file); if (tracking_id.notNull() && mLoadIntoTexturePipe) { diff --git a/indra/newview/gltf/buffer_util.h b/indra/newview/gltf/buffer_util.h index c231443a9e..53dee98cd1 100644 --- a/indra/newview/gltf/buffer_util.h +++ b/indra/newview/gltf/buffer_util.h @@ -141,6 +141,42 @@ namespace LL } template<> + inline void copyScalar<U32, LLVector4a>(U32* src, LLVector4a& dst) + { + dst.set((F32)*src, 0.f, 0.f, 0.f); + } + + template<> + inline void copyScalar<U16, LLVector4a>(U16* src, LLVector4a& dst) + { + dst.set((F32)*src, 0.f, 0.f, 0.f); + } + + template<> + inline void copyScalar<U8, LLVector4a>(U8* src, LLVector4a& dst) + { + dst.set((F32)*src, 0.f, 0.f, 0.f); + } + + template<> + inline void copyScalar<U32, LLVector2>(U32* src, LLVector2& dst) + { + dst.set((F32)*src, 0.f); + } + + template<> + inline void copyScalar<U16, LLVector2>(U16* src, LLVector2& dst) + { + dst.set((F32)*src, 0.f); + } + + template<> + inline void copyScalar<U8, LLVector2>(U8* src, LLVector2& dst) + { + dst.set((F32)*src, 0.f); + } + + template<> inline void copyVec2<F32, LLVector2>(F32* src, LLVector2& dst) { dst.set(src[0], src[1]); @@ -221,6 +257,12 @@ namespace LL } template<> + inline void copyVec4<U32, LLVector4a>(U32* src, LLVector4a& dst) + { + dst.set((F32)src[0], (F32)src[1], (F32)src[2], (F32)src[3]); + } + + template<> inline void copyVec4<U16, LLVector4a>(U16* src, LLVector4a& dst) { dst.set(src[0], src[1], src[2], src[3]); @@ -373,7 +415,7 @@ namespace LL } else { - LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL; + LL_ERRS("GLTF") << "Unsupported accessor type " << (S32)accessor.mType << LL_ENDL; } } diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp index 1af98c3730..66aa29d86b 100644 --- a/indra/newview/gltf/llgltfloader.cpp +++ b/indra/newview/gltf/llgltfloader.cpp @@ -826,7 +826,8 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const std::string& bas LL_DEBUGS("GLTF_IMPORT") << "No normals found for primitive, using default normal." << LL_ENDL; } - vert.uv0 = glm::vec2(prim.mTexCoords0[i][0], -prim.mTexCoords0[i][1]); + // Flip texture V coordinate + vert.uv0 = glm::vec2(prim.mTexCoords0[i][0], 1.f - prim.mTexCoords0[i][1]); if (skinIdx >= 0) { diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 0d7ad0a124..60af0cad05 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4850,6 +4850,8 @@ const std::string& LLAgent::getTeleportStateName() const void LLAgent::parseTeleportMessages(const std::string& xml_filename) { + LL_PROFILE_ZONE_SCOPED; + LLXMLNodePtr root; bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index f3265afebd..ece18fb5cc 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -144,6 +144,8 @@ LLAppCoreHttp::~LLAppCoreHttp() void LLAppCoreHttp::init() { + LL_PROFILE_ZONE_SCOPED; + LLCoreHttpUtil::setPropertyMethods( std::bind(&LLControlGroup::getBOOL, std::ref(gSavedSettings), std::placeholders::_1), std::bind(&LLControlGroup::declareBOOL, std::ref(gSavedSettings), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, LLControlVariable::PERSIST_NONDFT)); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8bf418aa44..ab4a0fbc28 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -340,9 +340,6 @@ F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME; S32 gPendingMetricsUploads = 0; - -bool gDisconnected = false; - // Used to restore texture state after a mode switch LLFrameTimer gRestoreGLTimer; bool gRestoreGL = false; @@ -735,6 +732,8 @@ public: bool LLAppViewer::init() { + LL_PROFILE_ZONE_SCOPED; + setupErrorHandling(mSecondInstance); // @@ -936,6 +935,7 @@ bool LLAppViewer::init() // Early out from user choice. LL_WARNS("InitInfo") << "initHardwareTest() failed." << LL_ENDL; // quit immediately + LL_PROFILER_FRAME_END; return false; } LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ; @@ -954,6 +954,7 @@ bool LLAppViewer::init() OSMessageBox(msg.c_str(), LLStringUtil::null, OSMB_OK); LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL; // quit immediately + LL_PROFILER_FRAME_END; return false; } LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; @@ -989,6 +990,7 @@ bool LLAppViewer::init() // Already handled with a MBVideoDrvErr LL_WARNS("InitInfo") << "gGLManager.mHasRequirements is false." << LL_ENDL; // quit immediately + LL_PROFILER_FRAME_END; return false; } @@ -1002,6 +1004,7 @@ bool LLAppViewer::init() OSMessageBox(msg.c_str(), LLStringUtil::null, OSMB_OK); LL_WARNS("InitInfo") << "SSE2 is not supported" << LL_ENDL; // quit immediately + LL_PROFILER_FRAME_END; return false; } #endif @@ -1240,7 +1243,7 @@ bool LLAppViewer::init() /*----------------------------------------------------------------------*/ // nat 2016-06-29 moved the following here from the former mainLoop(). - mMainloopTimeout = new LLWatchdogTimeout(); + mMainloopTimeout = new LLWatchdogTimeout("mainloop"); // Create IO Pump to use for HTTP Requests. gServicePump = new LLPumpIO(gAPRPoolp); @@ -1273,7 +1276,7 @@ bool LLAppViewer::init() gDirUtilp->deleteDirAndContents(gDirUtilp->getDumpLogsDirPath()); } #endif - + LL_PROFILER_FRAME_END; return true; } @@ -1430,12 +1433,14 @@ bool LLAppViewer::doFrame() { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df mainloop"); + pingMainloopTimeout("df mainloop"); // canonical per-frame event mainloop.post(newFrame); } { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df suspend"); + pingMainloopTimeout("df suspend"); // give listeners a chance to run llcoro::suspend(); // if one of our coroutines threw an uncaught exception, rethrow it now @@ -1471,6 +1476,7 @@ bool LLAppViewer::doFrame() { { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df pauseMainloopTimeout"); + pingMainloopTimeout("df idle"); // So that it will be aware of last state. pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! } @@ -1482,7 +1488,7 @@ bool LLAppViewer::doFrame() { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df resumeMainloopTimeout"); - resumeMainloopTimeout(); + resumeMainloopTimeout("df idle"); } } @@ -1497,7 +1503,7 @@ bool LLAppViewer::doFrame() } disconnectViewer(); - resumeMainloopTimeout(); + resumeMainloopTimeout("df snapshot n disconnect"); } // Render scene. @@ -2190,6 +2196,8 @@ void LLAppViewer::initGeneralThread() bool LLAppViewer::initThreads() { + LL_PROFILE_ZONE_SCOPED; + static const bool enable_threads = true; LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); @@ -2300,7 +2308,22 @@ void errorHandler(const std::string& title_string, const std::string& message_st } if (!message_string.empty()) { - OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); + if (on_main_thread()) + { + // Prevent watchdog from killing us while dialog is up. + // Can't do pauseMainloopTimeout, since this may be called + // from threads and we are not going to need watchdog now. + LLAppViewer::instance()->pauseMainloopTimeout(); + + // todo: might want to have non-crashing timeout for OOM cases + // and needs a way to pause main loop. + OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); + LLAppViewer::instance()->resumeMainloopTimeout(); + } + else + { + OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); + } } } @@ -3022,6 +3045,8 @@ bool LLAppViewer::initConfiguration() // keeps growing, necessitating a method all its own. void LLAppViewer::initStrings() { + LL_PROFILE_ZONE_SCOPED; + std::string strings_file = "strings.xml"; std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file); if (strings_path_full.empty() || !LLFile::isfile(strings_path_full)) @@ -3109,6 +3134,7 @@ void LLAppViewer::sendOutOfDiskSpaceNotification() bool LLAppViewer::initWindow() { + LL_PROFILE_ZONE_SCOPED; LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL; // store setting in a global for easy access and modification @@ -3164,7 +3190,19 @@ bool LLAppViewer::initWindow() if (use_watchdog) { - LLWatchdog::getInstance()->init(); + LLWatchdog::getInstance()->init([]() + { + LLAppViewer* app = LLAppViewer::instance(); + if (app->logoutRequestSent()) + { + app->createErrorMarker(LAST_EXEC_LOGOUT_FROZE); + } + else + { + app->createErrorMarker(LAST_EXEC_FROZE); + } + }); + gViewerWindow->getWindow()->initWatchdog(); } LLNotificationsUI::LLNotificationManager::getInstance(); @@ -4327,6 +4365,7 @@ U32 LLAppViewer::getObjectCacheVersion() bool LLAppViewer::initCache() { + LL_PROFILE_ZONE_SCOPED; mPurgeCache = false; bool read_only = mSecondInstance; LLAppViewer::getTextureCache()->setReadOnly(read_only) ; @@ -4420,19 +4459,22 @@ bool LLAppViewer::initCache() if (mPurgeCache) { - LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); - purgeCache(); + LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); + purgeCache(); // clear the new C++ file system based cache LLDiskCache::getInstance()->clearCache(); - } - else + } + else if (gSavedSettings.getBOOL("PurgeDiskCacheOnStartup")) { // purge excessive files from the new file system based cache LLDiskCache::getInstance()->purge(); } + + // Start disk cache purge thread to + // purge excessive files from the file system based cache + LLAppViewer::getPurgeDiskCacheThread()->start(); } - LLAppViewer::getPurgeDiskCacheThread()->start(); LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); @@ -4475,6 +4517,7 @@ void LLAppViewer::loadKeyBindings() // As per GHI #4498, remove old, stale CEF cache folders from previous sessions void LLAppViewer::purgeCefStaleCaches() { + LL_PROFILE_ZONE_SCOPED; // TODO: we really shouldn't use a hard coded name for the cache folder here... const std::string browser_parent_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache"); if (LLFile::isdir(browser_parent_cache)) @@ -4682,6 +4725,8 @@ std::string get_name_cache_filename(const std::string &base_file, const std::str void LLAppViewer::loadNameCache() { + LL_PROFILE_ZONE_SCOPED; + // display names cache std::string filename = get_name_cache_filename("avatar_name_cache", "xml"); LL_INFOS("AvNameCache") << filename << LL_ENDL; @@ -5829,7 +5874,7 @@ void LLAppViewer::initMainloopTimeout(std::string_view state) { if (!mMainloopTimeout) { - mMainloopTimeout = new LLWatchdogTimeout(); + mMainloopTimeout = new LLWatchdogTimeout("mainloop"); resumeMainloopTimeout(state); } } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 6b0d3e0b27..e1119419af 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -417,8 +417,6 @@ extern S32 gPendingMetricsUploads; extern F32 gSimLastTime; extern F32 gSimFrames; -extern bool gDisconnected; - extern LLFrameTimer gRestoreGLTimer; extern bool gRestoreGL; extern bool gUseWireframe; diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 80c7f8beca..de3ce901c1 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -47,7 +47,7 @@ S32 LLAvatarListItem::sLeftPadding = 0; S32 LLAvatarListItem::sNameRightPadding = 0; S32 LLAvatarListItem::sChildrenWidths[LLAvatarListItem::ALIC_COUNT]; -static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(&typeid(LLAvatarListItem::Params), "avatar_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(typeid(LLAvatarListItem::Params), "avatar_list_item"); LLAvatarListItem::Params::Params() : default_style("default_style"), diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 76e308a966..2c9d74ed97 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -680,6 +680,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) LLNotifications::instance().add("RevokedModifyRights",args, payload); } } + // update modify permissions flags for affected objects + LLViewerObject::markObjectsForUpdate(agent_id); (mBuddyInfo[agent_id])->setRightsFrom(new_rights); } } diff --git a/indra/newview/llcapabilityprovider.h b/indra/newview/llcapabilityprovider.h index 484bd2ef04..acc752588d 100644 --- a/indra/newview/llcapabilityprovider.h +++ b/indra/newview/llcapabilityprovider.h @@ -37,12 +37,12 @@ class LLCapabilityProvider { public: - virtual ~LLCapabilityProvider() {} + virtual ~LLCapabilityProvider() = default; /** * Get a capability URL, given a capability name. Returns empty string if * no such capability is defined on this provider. */ - virtual std::string getCapability(const std::string& name) const = 0; + virtual std::string getCapability(std::string_view name) const = 0; /** * Get host to which to send that capability request. */ diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index de3752d879..f1b46f0533 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -56,6 +56,7 @@ namespace Details private: void eventPollCoro(std::string url); + void handleMessage(const std::string& msg_name, const LLSD& body); void handleMessage(const LLSD &content); bool mDone; @@ -95,21 +96,23 @@ namespace Details mSenderIp = sender.getIPandPort(); } + void LLEventPollImpl::handleMessage(const std::string &msg_name, const LLSD &body) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; + LLSD message; + message["sender"] = mSenderIp; + message["body"] = body; + + LLMessageSystem::dispatch(msg_name, message); + } + void LLEventPollImpl::handleMessage(const LLSD& content) { LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; std::string msg_name = content["message"].asString(); LLSD message; - try - { - message["sender"] = mSenderIp; - message["body"] = content["body"]; - } - catch (std::bad_alloc&) - { - LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Bad memory allocation on message: " << msg_name << LL_ENDL; - } + message["sender"] = mSenderIp; + message["body"] = content["body"]; LLMessageSystem::dispatch(msg_name, message); } @@ -194,7 +197,7 @@ namespace Details break; } - LLSD httpResults = result["http_result"]; + LLSD &httpResults = result["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); if (!status) @@ -299,7 +302,7 @@ namespace Details } acknowledge = result["id"]; - LLSD events = result["events"]; + LLSD &events = result["events"]; if (acknowledge.isUndefined()) { @@ -310,20 +313,37 @@ namespace Details LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << acknowledge << ")" << LL_ENDL; - LLSD::array_const_iterator i = events.beginArray(); - LLSD::array_const_iterator end = events.endArray(); + LLSD::array_iterator i = events.beginArray(); + LLSD::array_iterator end = events.endArray(); for (; i != end; ++i) { if (i->has("message")) { if (main_queue) - { // shuttle to a sensible spot in the main thread instead + { + // Shuttle copy to a sensible spot in the main thread instead // of wherever this coroutine happens to be executing - const LLSD& msg = *i; - main_queue->post([this, msg]() + + LL::WorkQueue::Work work; + { + // LLSD is too smart for it's own good and may act like a smart + // pointer for the content of (*i), so instead of passing (*i) + // pass a prepared name and move ownership of "body", + // as we are not going to need "body" anywhere else. + std::string msg_name = (*i)["message"].asString(); + + // WARNING: This is a shallow copy! + // If something still retains the data (like in httpAdapter?) this might still + // result in a crash, if it does appear to be the case, make a deep copy or + // convert data to string and pass that string. + const LLSD body = (*i)["body"]; + (*i)["body"].clear(); + work = [this, msg_name, body]() { - handleMessage(msg); - }); + handleMessage(msg_name, body); + }; + } + main_queue->post(work); } else { diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp index 193a42f9f6..c3aad4ee65 100644 --- a/indra/newview/llexternaleditor.cpp +++ b/indra/newview/llexternaleditor.cpp @@ -46,9 +46,13 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env { LL_INFOS() << "Editor command is empty or not set, falling back to OS open handler" << LL_ENDL; #if LL_WINDOWS - static const std::string os_cmd = "%SystemRoot%\\explorer.exe \"%s\""; + std::string os_cmd = LLStringUtil::getenv("SystemRoot", ""); + if (!os_cmd.empty()) + { + os_cmd.append("\\explorer.exe \"%s\""); + } #elif LL_DARWIN - static const std::string os_cmd = "/usr/bin/open \"%s\""; + static const std::string os_cmd = "/usr/bin/open -t \"%s\""; #elif LL_LINUX static const std::string os_cmd = "/usr/bin/xdg-open \"%s\""; #endif diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 377710c170..98b3ca820b 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1395,6 +1395,19 @@ bool LLFavoritesBarCtrl::enableSelected(const LLSD& userdata) { return !LLAgentPicksInfo::getInstance()->isPickLimitReached(); } + else if (param == "copy_slurl" + || param == "show_on_map") + { + LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID); + if (nullptr == item) + return false; // shouldn't happen as it is selected from existing items + + const LLUUID& asset_id = item->getAssetUUID(); + + // Favorites are supposed to be loaded first, it should be here already + LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL /*callback*/); + return nullptr != landmark; + } return false; } @@ -1425,10 +1438,17 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) LLVector3d posGlobal; LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal); + // inventory item and asset exist, otherwise + // enableSelected wouldn't have let it get here, + // only need to check location validity if (!posGlobal.isExactlyZero()) { LLLandmarkActions::getSLURLfromPosGlobal(posGlobal, copy_slurl_to_clipboard_cb); } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } } else if (action == "show_on_map") { @@ -1437,10 +1457,20 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) LLVector3d posGlobal; LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal); - if (!posGlobal.isExactlyZero() && worldmap_instance) + if (worldmap_instance) { - worldmap_instance->trackLocation(posGlobal); - LLFloaterReg::showInstance("world_map", "center"); + // inventory item and asset exist, otherwise + // enableSelected wouldn't have let it get here, + // only need to check location validity + if (!posGlobal.isExactlyZero()) + { + worldmap_instance->trackLocation(posGlobal); + LLFloaterReg::showInstance("world_map", "center"); + } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } } } else if (action == "create_pick") diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm index 6921cd6101..7262d18483 100644 --- a/indra/newview/llfilepicker_mac.mm +++ b/indra/newview/llfilepicker_mac.mm @@ -241,8 +241,13 @@ void doSaveDialogModeless(const std::string* file, NSURL* url = [NSURL fileURLWithPath:fileName]; [panel setNameFieldStringValue: fileName]; - [panel setDirectoryURL: url]; + NSURL *last_url = [[NSUserDefaults standardUserDefaults] URLForKey:@"NSNavLastRootDirectory"]; + if(!last_url) + { + NSURL *documents_url = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject; + [panel setDirectoryURL:documents_url]; + } [panel beginWithCompletionHandler:^(NSModalResponse result) { diff --git a/indra/newview/llfloatermarketplace.cpp b/indra/newview/llfloatermarketplace.cpp index 2a67e75fec..bb2378d864 100644 --- a/indra/newview/llfloatermarketplace.cpp +++ b/indra/newview/llfloatermarketplace.cpp @@ -56,6 +56,7 @@ void LLFloaterMarketplace::onOpen(const LLSD& key) else { openMarketplaceURL(params.url); + set_current_url(params.url); // Fix looping back to previous url when using the viewer navigation bar } } diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index ac8477a615..b784419780 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -170,7 +170,7 @@ namespace void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::string& data_in) { - std::istringstream str(data_in); + boost::iostreams::stream<boost::iostreams::array_source> str(data_in.data(), data_in.size()); LLSD data; diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp index a435a4f7c7..aa6ba6d023 100644 --- a/indra/newview/llinventorylistitem.cpp +++ b/indra/newview/llinventorylistitem.cpp @@ -41,7 +41,7 @@ #include "llinventorymodel.h" #include "llviewerinventory.h" -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(&typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item"); constexpr S32 WIDGET_SPACING = 3; constexpr S32 FAVORITE_IMAGE_SIZE = 14; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 01ff01e233..870f0873b9 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3425,6 +3425,7 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, LLSD inventory; if (!is_cache_obsolete) { + LL_PROFILE_ZONE_NAMED("inventory load from file - llsd parse"); LLPointer<LLSDParser> parser = new LLSDBinaryParser(); if (parser->parse(file, inventory, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) @@ -3436,56 +3437,61 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, if (!is_cache_obsolete) { - const LLSD& llsd_cats = inventory["categories"]; - if (llsd_cats.isArray()) { - LLSD::array_const_iterator iter = llsd_cats.beginArray(); - LLSD::array_const_iterator end = llsd_cats.endArray(); - for (; iter != end; ++iter) + LL_PROFILE_ZONE_NAMED("inventory load from file - categories"); + const LLSD& llsd_cats = inventory["categories"]; + if (llsd_cats.isArray()) { - LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null); - if (inv_cat->importLLSDMap(*iter)) + LLSD::array_const_iterator iter = llsd_cats.beginArray(); + LLSD::array_const_iterator end = llsd_cats.endArray(); + for (; iter != end; ++iter) { - categories.push_back(inv_cat); + LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null); + if (inv_cat->importLLSDMap(*iter)) + { + categories.push_back(inv_cat); + } } } } - const LLSD& llsd_items = inventory["items"]; - if (llsd_items.isArray()) { - LLSD::array_const_iterator iter = llsd_items.beginArray(); - LLSD::array_const_iterator end = llsd_items.endArray(); - for (; iter != end; ++iter) + LL_PROFILE_ZONE_NAMED("inventory load from file - items"); + const LLSD& llsd_items = inventory["items"]; + if (llsd_items.isArray()) { - LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem; - if (inv_item->fromLLSD(*iter)) + LLSD::array_const_iterator iter = llsd_items.beginArray(); + LLSD::array_const_iterator end = llsd_items.endArray(); + for (; iter != end; ++iter) { - if (inv_item->getUUID().isNull()) + LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem; + if (inv_item->fromLLSD(*iter)) { - LL_DEBUGS(LOG_INV) << "Ignoring inventory with null item id: " - << inv_item->getName() << LL_ENDL; - } - else - { - if (inv_item->getType() == LLAssetType::AT_UNKNOWN) + if (inv_item->getUUID().isNull()) { - cats_to_update.insert(inv_item->getParentUUID()); + LL_DEBUGS(LOG_INV) << "Ignoring inventory with null item id: " << inv_item->getName() << LL_ENDL; } else { - items.push_back(inv_item); + if (inv_item->getType() == LLAssetType::AT_UNKNOWN) + { + cats_to_update.insert(inv_item->getParentUUID()); + } + else + { + items.push_back(inv_item); + } } } - } - // TODO(brad) - figure out how to reenable this without breaking everything else - // static constexpr U64 BATCH_SIZE = 512U; - // if ((++lines_count % BATCH_SIZE) == 0) - // { - // // SL-19968 - make sure message system code gets a chance to run every so often - // pump_idle_startup_network(); - // } + // TODO(brad) - figure out how to reenable this without breaking everything else + // static constexpr U64 BATCH_SIZE = 512U; + // if ((++lines_count % BATCH_SIZE) == 0) + // { + // // SL-19968 - make sure message system code gets a chance to run every so often + // pump_idle_startup_network(); + // } + } } } } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 9fbabec8f3..05ada9121a 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -201,13 +201,13 @@ private: // the inventory using several different identifiers. // mInventory member data is the 'master' list of inventory, and // mCategoryMap and mItemMap store uuid->object mappings. - typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t; - typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t; + typedef std::unordered_map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t; + typedef std::unordered_map<LLUUID, LLPointer<LLViewerInventoryItem>> item_map_t; cat_map_t mCategoryMap; item_map_t mItemMap; // This last set of indices is used to map parents to children. - typedef std::map<LLUUID, cat_array_t*> parent_cat_map_t; - typedef std::map<LLUUID, item_array_t*> parent_item_map_t; + typedef std::unordered_map<LLUUID, cat_array_t*> parent_cat_map_t; + typedef std::unordered_map<LLUUID, item_array_t*> parent_item_map_t; parent_cat_map_t mParentChildCategoryTree; parent_item_map_t mParentChildItemTree; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 8d57a4e7bb..06dd830416 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2125,8 +2125,7 @@ LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) { LL_PROFILE_ZONE_SCOPED; - std::map<LLUUID, LLFolderViewItem*>::iterator map_it; - map_it = mItemMap.find(id); + auto map_it = mItemMap.find(id); if (map_it != mItemMap.end()) { return map_it->second; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index dc2e304ab3..ca2d5814bc 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -300,7 +300,7 @@ protected: LLPointer<LLFolderViewGroupedItemBridge> mGroupedItemBridge; Params mParams; // stored copy of parameter block - std::map<LLUUID, LLFolderViewItem*> mItemMap; + std::unordered_map<LLUUID, LLFolderViewItem*> mItemMap; /** * Pointer to LLInventoryFolderViewModelBuilder. * diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index 3fa0ab99f3..b25a42a938 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -147,29 +147,66 @@ void LLLandmarkList::processGetAssetReply( else { // failed to parse, shouldn't happen + LL_WARNS("Landmarks") << "Failed to parse landmark " << uuid << LL_ENDL; gLandmarkList.eraseCallbacks(uuid); } } else { // got a good status, but no file, shouldn't happen + LL_WARNS("Landmarks") << "Empty buffer for landmark " << uuid << LL_ENDL; gLandmarkList.eraseCallbacks(uuid); } + + // We got this asset, remove it from retry and bad lists. + gLandmarkList.mRetryList.erase(uuid); + gLandmarkList.mBadList.erase(uuid); } else { - // SJB: No use case for a notification here. Use LL_DEBUGS() instead - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) + if (LL_ERR_NO_CAP == status) + { + // A problem with asset cap, always allow retrying. + // Todo: should this reschedule? + gLandmarkList.mRequestedList.erase(uuid); + gLandmarkList.eraseCallbacks(uuid); + // If there was a previous request, it likely failed due to an obsolete cap + // so clear the retry marker to allow multiple retries. + gLandmarkList.mRetryList.erase(uuid); + return; + } + if (gLandmarkList.mBadList.find(uuid) != gLandmarkList.mBadList.end()) + { + // Already on the 'bad' list, ignore + gLandmarkList.mRequestedList.erase(uuid); + gLandmarkList.eraseCallbacks(uuid); + return; + } + if (LL_ERR_ASSET_REQUEST_FAILED == status + && gLandmarkList.mRetryList.find(uuid) == gLandmarkList.mRetryList.end()) + { + // There is a number of reasons why an asset request can fail, + // like a cap being obsolete due to user teleporting. + // Let viewer rerequest at least once more. + // Todo: should this reshchedule? + gLandmarkList.mRetryList.emplace(uuid); + gLandmarkList.mRequestedList.erase(uuid); + gLandmarkList.eraseCallbacks(uuid); + return; + } + + if (LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status) { - LL_WARNS("Landmarks") << "Missing Landmark" << LL_ENDL; - //LLNotificationsUtil::add("LandmarkMissing"); + LL_WARNS("Landmarks") << "Missing Landmark " << uuid << LL_ENDL; } else { - LL_WARNS("Landmarks") << "Unable to load Landmark" << LL_ENDL; - //LLNotificationsUtil::add("UnableToLoadLandmark"); + LL_WARNS("Landmarks") << "Unable to load Landmark " << uuid + << ". asset status: " << status + << ". Extended status: " << (S64)ext_status << LL_ENDL; } + gLandmarkList.mRetryList.erase(uuid); gLandmarkList.mBadList.insert(uuid); gLandmarkList.mRequestedList.erase(uuid); //mBadList effectively blocks any load, so no point keeping id in requests gLandmarkList.eraseCallbacks(uuid); diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h index fb8b5a1960..76b5b97211 100644 --- a/indra/newview/lllandmarklist.h +++ b/indra/newview/lllandmarklist.h @@ -72,6 +72,7 @@ protected: typedef std::set<LLUUID> landmark_uuid_list_t; landmark_uuid_list_t mBadList; + landmark_uuid_list_t mRetryList; typedef std::map<LLUUID,F32> landmark_requested_list_t; landmark_requested_list_t mRequestedList; diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp index 51c38aba3a..0a90cf0699 100644 --- a/indra/newview/llmachineid.cpp +++ b/indra/newview/llmachineid.cpp @@ -398,6 +398,8 @@ bool getSerialNumber(unsigned char *unique_id, size_t len) S32 LLMachineID::init() { + LL_PROFILE_ZONE_SCOPED; + size_t len = sizeof(static_unique_id); memset(static_unique_id, 0, len); S32 ret_code = 0; diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index ac4c18d60c..5fc0b1b290 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -33,9 +33,42 @@ #include "httprequest.h" #include "httpheaders.h" #include "httpoptions.h" +#include <boost/container_hash/hash.hpp> class LLViewerRegion; +// struct for TE-specific material ID query +class TEMaterialPair +{ +public: + U32 te; + LLMaterialID materialID; + + bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); } +}; + +inline bool operator<(const TEMaterialPair& lhs, const TEMaterialPair& rhs) +{ + return (lhs.te < rhs.te) ? true : (lhs.materialID < rhs.materialID); +} + +// std::hash implementation for TEMaterialPair +namespace std +{ + template<> + struct hash<TEMaterialPair> + { + inline size_t operator()(const TEMaterialPair& p) const noexcept + { + // Utilize boost::hash_combine to generate a good hash + size_t seed = 0; + boost::hash_combine(seed, p.te + 1); + boost::hash_combine(seed, p.materialID); + return seed; + } + }; +} // namespace std + class LLMaterialMgr : public LLSingleton<LLMaterialMgr> { LLSINGLETON(LLMaterialMgr); @@ -83,29 +116,6 @@ private: void onRegionRemoved(LLViewerRegion* regionp); private: - // struct for TE-specific material ID query - class TEMaterialPair - { - public: - - U32 te; - LLMaterialID materialID; - - bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); } - }; - - // definitions follow class - friend std::hash<TEMaterialPair>; - friend size_t hash_value(const TEMaterialPair&) noexcept; - - friend inline bool operator<( - const LLMaterialMgr::TEMaterialPair& lhs, - const LLMaterialMgr::TEMaterialPair& rhs) - { - return (lhs.te < rhs.te) ? true : - (lhs.materialID < rhs.materialID); - } - typedef std::set<LLMaterialID> material_queue_t; typedef std::map<LLUUID, material_queue_t> get_queue_t; typedef std::pair<const LLUUID, LLMaterialID> pending_material_t; @@ -113,7 +123,7 @@ private: typedef std::map<LLMaterialID, std::unique_ptr<get_callback_t>> get_callback_map_t; - typedef boost::unordered_map<TEMaterialPair, std::unique_ptr<get_callback_te_t>> get_callback_te_map_t; + typedef std::unordered_map<TEMaterialPair, std::unique_ptr<get_callback_te_t>> get_callback_te_map_t; typedef std::set<LLUUID> getall_queue_t; typedef std::map<LLUUID, F64> getall_pending_map_t; typedef std::map<LLUUID, std::unique_ptr<getall_callback_t>> getall_callback_map_t; @@ -142,23 +152,5 @@ private: U32 getMaxEntries(const LLViewerRegion* regionp); }; -// std::hash implementation for TEMaterialPair -namespace std -{ - template<> struct hash<LLMaterialMgr::TEMaterialPair> - { - inline size_t operator()(const LLMaterialMgr::TEMaterialPair& p) const noexcept - { - return size_t((p.te + 1) * p.materialID.getDigest64()); - } - }; -} - -// For use with boost containers. -inline size_t hash_value(const LLMaterialMgr::TEMaterialPair& p) noexcept -{ - return size_t((p.te + 1) * p.materialID.getDigest64()); -} - #endif // LL_LLMATERIALMGR_H diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 56ad8297c7..061b4b5428 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -442,7 +442,7 @@ public: LLCondition* mSignal; //map of known mesh headers - typedef boost::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data + typedef std::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data mesh_header_map mMeshHeader; class HeaderRequest : public RequestStats diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index ed5ab35439..bc9ca46672 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -3461,7 +3461,7 @@ bool LLModelPreview::render() LLViewerCamera::getInstance()->setAspect(aspect); - LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); + LLViewerCamera::getInstance()->setViewNoBroadcast(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); LLVector3 offset = mCameraOffset; LLVector3 target_pos = mPreviewTarget + offset; diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 35d36affa2..9035baafcd 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -582,6 +582,8 @@ std::vector<LLMute> LLMuteList::getMutes() const //----------------------------------------------------------------------------- bool LLMuteList::loadFromFile(const std::string& filename) { + LL_PROFILE_ZONE_SCOPED; + if(!filename.size()) { LL_WARNS() << "Mute List Filename is Empty!" << LL_ENDL; @@ -962,6 +964,8 @@ bool LLRenderMuteList::saveToFile() bool LLRenderMuteList::loadFromFile() { + LL_PROFILE_ZONE_SCOPED; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "render_mute_settings.txt"); LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("rb")); if (!fp) diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 8a070babcd..9b21a217db 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -850,7 +850,12 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id) // Start observing changes in "My Outfits" category. mCategoriesObserver->addCategory(cat_id, - boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id), true); + [this, cat_id]() + { + mPendingOutfitRefreshes.insert(cat_id); + startIdleLoop(cat_id); + }, + true); outfit_category->fetch(); refreshOutfit(cat_id); @@ -901,6 +906,18 @@ void LLOutfitGallery::updateChangedCategoryName(LLViewerInventoryCategory *cat, } } +bool LLOutfitGallery::updateOneOutfit() +{ + if (mPendingOutfitRefreshes.empty()) + return false; + + auto it = mPendingOutfitRefreshes.begin(); + LLUUID outfit_id = *it; + mPendingOutfitRefreshes.erase(it); + refreshOutfit(outfit_id); + return true; +} + void LLOutfitGallery::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) { if (mOutfitMenu && cat_id.notNull()) diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h index 5801a32a39..183b6ea9d5 100644 --- a/indra/newview/lloutfitgallery.h +++ b/indra/newview/lloutfitgallery.h @@ -98,6 +98,7 @@ public: /*virtual*/ void updateAddedCategory(LLUUID cat_id); /*virtual*/ void updateRemovedCategory(LLUUID cat_id); /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name); + /*virtual*/ bool updateOneOutfit(); // bulk processing, scheduled by observer when updates are needed /*virtual*/ bool hasItemSelected(); /*virtual*/ bool canWearSelected(); @@ -190,6 +191,7 @@ private: typedef item_num_map_t::value_type item_numb_map_value_t; item_num_map_t mItemIndexMap; std::map<S32, LLOutfitGalleryItem*> mIndexToItemMap; + std::set<LLUUID> mPendingOutfitRefreshes; LLInventoryCategoriesObserver* mOutfitsObserver; diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 32831fcd9b..7db79c7010 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -1055,6 +1055,15 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) } } +void LLOutfitListBase::startIdleLoop(const LLUUID cat_id) +{ + if (mRefreshListState.CategoryUUID.isNull()) + { + mRefreshListState.CategoryUUID = cat_id; + gIdleCallbacks.addFunction(onIdle, this); + } +} + // static void LLOutfitListBase::onIdle(void* userdata) { @@ -1129,6 +1138,14 @@ void LLOutfitListBase::onIdleRefreshList() return; } + // Let derived classes process their own updates. + while (updateOneOutfit()) + { + curent_time = LLTimer::getTotalSeconds(); + if (curent_time >= end_time) + return; + } + sortOutfits(); highlightBaseOutfit(); diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index bcf7e45696..408ff07116 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -95,6 +95,17 @@ public: virtual void updateAddedCategory(LLUUID cat_id) = 0; virtual void updateRemovedCategory(LLUUID cat_id) = 0; virtual void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) = 0; + + /* + * Optional hook for derived classes to perform additional processing. + * This is called by the outfit list update logic after the core + * bookkeeping for an outfit has been handled. + * + * @return true if update processing should continue, + * false if no additional work is required. + * The base implementation returns false. + */ + virtual bool updateOneOutfit() { return false; }; virtual void sortOutfits(); void removeSelected(); @@ -138,6 +149,7 @@ protected: bool isOutfitFolder(LLViewerInventoryCategory* cat) const; + void startIdleLoop(const LLUUID cat_id); static void onIdle(void* userdata); void onIdleRefreshList(); @@ -150,6 +162,7 @@ protected: uuid_vec_t::const_iterator RemovedIterator; } mRefreshListState; std::set<LLUUID> mChangedItems; + std::set<LLUUID> mPendingOutfitRefreshes; bool mIsInitialized; LLInventoryCategoriesObserver* mCategoriesObserver; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index de8ab95dee..bcb51b22ca 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1201,7 +1201,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) // See if that's been overridden by a material setting for same... // - LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode, mIsAlpha); + LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode); // it is invalid to have any alpha mode other than blend if transparency is greater than zero ... // Want masking? Want emissive? Tough! You get BLEND! @@ -1211,6 +1211,12 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) alpha_mode = mIsAlpha ? alpha_mode : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; mComboAlphaMode->getSelectionInterface()->selectNthItem(alpha_mode); + mComboAlphaMode->setTentative(!identical_alpha_mode); + if (!identical_alpha_mode) + { + std::string multiple = LLTrans::getString("multiple_textures"); + mComboAlphaMode->setLabel(multiple); + } updateAlphaControls(); mExcludeWater &= (LLMaterial::DIFFUSE_ALPHA_MODE_BLEND == alpha_mode); @@ -5484,32 +5490,40 @@ void LLPanelFace::LLSelectedTEMaterial::getMaxNormalRepeats(F32& repeats, bool& identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_norm_repeats_func, repeats); } -void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha) +void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical) { struct LLSelectedTEGetDiffuseAlphaMode : public LLSelectedTEGetFunctor<U8> { - LLSelectedTEGetDiffuseAlphaMode() : _isAlpha(false) {} - LLSelectedTEGetDiffuseAlphaMode(bool diffuse_texture_has_alpha) : _isAlpha(diffuse_texture_has_alpha) {} + LLSelectedTEGetDiffuseAlphaMode() {} virtual ~LLSelectedTEGetDiffuseAlphaMode() {} U8 get(LLViewerObject* object, S32 face) { - U8 diffuse_mode = _isAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - LLTextureEntry* tep = object->getTE(face); if (tep) { LLMaterial* mat = tep->getMaterialParams().get(); if (mat) { - diffuse_mode = mat->getDiffuseAlphaMode(); + return mat->getDiffuseAlphaMode(); + } + } + + bool has_alpha = false; + LLViewerTexture* image = object->getTEImage(face); + if (image) + { + LLGLenum format = image->getPrimaryFormat(); + if (format == GL_RGBA || format == GL_ALPHA) + { + has_alpha = true; } } + U8 diffuse_mode = has_alpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; return diffuse_mode; } - bool _isAlpha; // whether or not the diffuse texture selected contains alpha information - } get_diff_mode(diffuse_texture_has_alpha); + } get_diff_mode; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &get_diff_mode, diffuse_alpha_mode); } diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 63fee6bab8..82790ac54b 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -652,7 +652,7 @@ public: static void getCurrent(LLMaterialPtr& material_ptr, bool& identical_material); static void getMaxSpecularRepeats(F32& repeats, bool& identical); static void getMaxNormalRepeats(F32& repeats, bool& identical); - static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha); + static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical); static void selectionNormalScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter); static void selectionSpecularScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 00b592d86e..868e02f28b 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -220,6 +220,11 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, // STEAM-14: When user presses Enter with this field in focus, initiate login password_edit->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, false)); + childSetAction("connect_btn", onClickConnect, this); + + mLoginBtn = getChild<LLButton>("connect_btn"); + setDefaultBtn(mLoginBtn); + // change z sort of clickable text to be behind buttons sendChildToBack(getChildView("forgot_password_text")); sendChildToBack(getChildView("sign_up_text")); @@ -296,11 +301,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, onUpdateStartSLURL(start_slurl); // updates grid if needed } - childSetAction("connect_btn", onClickConnect, this); - - mLoginBtn = getChild<LLButton>("connect_btn"); - setDefaultBtn(mLoginBtn); - std::string channel = LLVersionInfo::instance().getChannel(); std::string version = stringize(LLVersionInfo::instance().getShortVersion(), " (", LLVersionInfo::instance().getBuild(), ')'); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index a31a54bb67..d27ce81e4f 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1830,7 +1830,7 @@ void LLPanelObjectInventory::onFocusReceived() LLFolderViewItem* LLPanelObjectInventory::getItemByID( const LLUUID& id ) { - std::map<LLUUID, LLFolderViewItem*>::iterator map_it = mItemMap.find(id); + auto map_it = mItemMap.find(id); if (map_it != mItemMap.end()) { return map_it->second; diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 154639e4bb..13e27b489c 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -109,7 +109,7 @@ protected: bool isSelectionRemovable(); private: - std::map<LLUUID, LLFolderViewItem*> mItemMap; + std::unordered_map<LLUUID, LLFolderViewItem*> mItemMap; LLScrollContainer* mScroller; LLFolderView* mFolders; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 87f05f2028..c380b6860f 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -517,7 +517,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, std::string parcel_owner = LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString(); mParcelOwner->setText(parcel_owner); - LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); mRegionGroupText->setText( getString("none_text")); } @@ -548,7 +548,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID(); if(auth_buyer_id.notNull()) { - LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); // Show sales info to a specific person or a group he belongs to. if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id)) diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index f562be0f5d..0c161198f8 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -118,6 +118,8 @@ private: LLTextEditor* mResaleText; LLTextBox* mSaleToText; LLAccordionCtrl* mAccordionCtrl; + + boost::signals2::scoped_connection mAvatarNameCacheConnection; }; #endif // LL_LLPANELPLACEPROFILE_H diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index b81b891685..7396f079b0 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -110,7 +110,11 @@ void LLPanelSnapshotInventory::updateControls(const LLSD& info) void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) { - bool current_window_selected = (getChild<LLComboBox>(getImageSizeComboName())->getCurrentIndex() == 3); + LLComboBox* combo = getChild<LLComboBox>(getImageSizeComboName()); + // Current window likely won't ever change position from being the penultimate item + // Custom window is last item + S32 curent_window_index = combo->getItemCount() - 2; + bool current_window_selected = (combo->getCurrentIndex() == curent_window_index); getChild<LLSpinCtrl>(getWidthSpinnerName())->setVisible(!current_window_selected); getChild<LLSpinCtrl>(getHeightSpinnerName())->setVisible(!current_window_selected); } diff --git a/indra/newview/llperfstats.h b/indra/newview/llperfstats.h index 1a2098ec7e..38deb87237 100644 --- a/indra/newview/llperfstats.h +++ b/indra/newview/llperfstats.h @@ -223,7 +223,7 @@ namespace LLPerfStats static void updateMeanFrameTime(U64 tot_frame_time_raw); // StatsArray is a uint64_t for each possible statistic type. using StatsArray = std::array<uint64_t, static_cast<size_t>(LLPerfStats::StatType_t::STATS_COUNT)>; - using StatsMap = std::unordered_map<LLUUID, StatsArray, boost::hash<LLUUID>>; + using StatsMap = std::unordered_map<LLUUID, StatsArray>; using StatsTypeMatrix = std::array<StatsMap, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>; using StatsSummaryArray = std::array<StatsArray, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>; diff --git a/indra/newview/llscriptruntimeperms.h b/indra/newview/llscriptruntimeperms.h index 300304c21b..6350b61d08 100644 --- a/indra/newview/llscriptruntimeperms.h +++ b/indra/newview/llscriptruntimeperms.h @@ -24,10 +24,7 @@ * $/LicenseInfo$ */ -#ifndef LL_LLSCRIPTRUNTIME_PERMS_H -#define LL_LLSCRIPTRUNTIME_PERMS_H - -#include <boost/array.hpp> +#pragma once typedef struct _script_perm { std::string question; @@ -37,12 +34,12 @@ typedef struct _script_perm { question(q), permbit(b), caution(c) {} } script_perm_t; -const U32 NUM_SCRIPT_PERMISSIONS = 18; +const U32 NUM_SCRIPT_PERMISSIONS = 19; const S32 SCRIPT_PERMISSION_DEBIT = 0; const S32 SCRIPT_PERMISSION_TRIGGER_ANIMATION = 3; const S32 SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS = 14; -static const boost::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSIONS = {{ +static const std::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSIONS = {{ _script_perm("ScriptTakeMoney", (0x1 << 1), true), _script_perm("ActOnControlInputs", (0x1 << 2), false), _script_perm("RemapControlInputs", (0x1 << 3), false), @@ -60,7 +57,7 @@ static const boost::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSI _script_perm("OverrideYourAnimations", (0x1 << 15), false), _script_perm("ScriptReturnObjects", (0x1 << 16), false), _script_perm("ForceSitAvatar", (0x1 << 17), false), - _script_perm("ChangeEnvSettings", (0x1 << 18), false) + _script_perm("ChangeEnvSettings", (0x1 << 18), false), + _script_perm("PrivilegedLandAccess",(0x1 << 19), true) } }; -#endif // LL_LLSCRIPTRUNTIME_PERMS_H diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index a624682e11..7cf626f632 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6193,6 +6193,15 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use node->mCategory = category; node->mName.assign(name); node->mDescription.assign(desc); + + LLViewerObject* obj = node->getObject(); + if (obj && LLViewerObject::isObjectInPendingUpdate(owner_id, obj)) + { + // current response doesn't return modify permissions flags, + // so we should request it separately if needed + obj->requestObjectUpdate(); + } + } dialog_refresh_all(); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index b0b929a3ef..00b6bc09e9 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -986,6 +986,8 @@ void LLTextureCache::setReadOnly(bool read_only) // Returns the unused amount of max_size if any S64 LLTextureCache::initCache(ELLPath location, S64 max_size, bool texture_cache_mismatch) { + LL_PROFILE_ZONE_SCOPED; + llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized. S64 entries_size = (max_size * 36) / 100; //0.36 * max_size diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp index 25dc0982b8..55e178e084 100644 --- a/indra/newview/lltoastscriptquestion.cpp +++ b/indra/newview/lltoastscriptquestion.cpp @@ -48,7 +48,12 @@ bool LLToastScriptQuestion::postBuild() LLTextBox* mFooter = getChild<LLTextBox>("bottom_info_message"); mMessage->setValue(mNotification->getMessage()); - mFooter->setValue(mNotification->getFooter()); + std::string footer = mNotification->getFooter(); + mFooter->setValue(footer); + if (footer.empty()) + { + mFooter->setVisible(false); + } snapToMessageHeight(); @@ -78,21 +83,69 @@ void LLToastScriptQuestion::snapToMessageHeight() if (mMessage->getVisible() && mFooter->getVisible()) { - S32 heightDelta = 0; - S32 maxTextHeight = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT) + S32 height_delta = 0; + S32 max_text_height = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT) + (mFooter->getFont()->getLineHeight() * MAX_LINES_COUNT); - LLRect messageRect = mMessage->getRect(); - LLRect footerRect = mFooter->getRect(); + LLRect message_rect = mMessage->getRect(); + + S32 old_message_height = message_rect.getHeight(); + S32 new_message_height = mMessage->getTextBoundingRect().getHeight(); + S32 new_footer_height = mFooter->getTextBoundingRect().getHeight(); + + constexpr S32 FOOTER_PADDING = 8; // new height should include padding for newly added footer + S32 required_text_height = new_message_height + new_footer_height + FOOTER_PADDING; + S32 new_text_height = llmin(required_text_height, max_text_height); + + // Footer was invisible, so use old_message_height for old height + height_delta = new_text_height - old_message_height; + + reshape( getRect().getWidth(), llmax(getRect().getHeight() + height_delta, MIN_PANEL_HEIGHT)); + + // Floater was resized, now resize and shift children + // Message follows top, so it's top is in a correct position, but needs to be resized down + S32 message_delta = new_message_height - old_message_height; + message_rect = mMessage->getRect(); // refresh since it might have changed after reshape + message_rect.mBottom = message_rect.mBottom - message_delta; + mMessage->setRect(message_rect); + mMessage->needsReflow(); + // Button panel should stay the same size, just translate it + LLPanel* panel = getChild<LLPanel>("buttons_panel"); + panel->translate(0, -message_delta); + // Footer should be both moved and resized + LLRect footer_rect = mFooter->getRect(); + footer_rect.mTop = footer_rect.mTop - message_delta; + footer_rect.mBottom = footer_rect.mTop - new_footer_height; + mFooter->setRect(footer_rect); + mFooter->needsReflow(); + } + else if (mMessage->getVisible()) + { + S32 height_delta = 0; + S32 max_text_height = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT); + + LLRect message_rect = mMessage->getRect(); + + S32 old_message_height = message_rect.getHeight(); + S32 new_message_height = mMessage->getTextBoundingRect().getHeight(); - S32 oldTextHeight = messageRect.getHeight() + footerRect.getHeight(); + S32 new_text_height = llmin(new_message_height, max_text_height); - S32 requiredTextHeight = mMessage->getTextBoundingRect().getHeight() + mFooter->getTextBoundingRect().getHeight(); - S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); + // Footer was invisible, so use old_message_height for old height + height_delta = new_text_height - old_message_height; - heightDelta = newTextHeight - oldTextHeight - heightDelta; + reshape(getRect().getWidth(), llmax(getRect().getHeight() + height_delta, MIN_PANEL_HEIGHT)); - reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); + // Floater was resized, now resize and shift children + // Message follows top, so it's top is in a correct position, but needs to be resized down + S32 message_delta = new_message_height - old_message_height; + message_rect = mMessage->getRect(); // refresh since it might have changed after reshape + message_rect.mBottom = message_rect.mBottom - message_delta; + mMessage->setRect(message_rect); + mMessage->needsReflow(); + // Button panel should stay the same size, just translate it + LLPanel* panel = getChild<LLPanel>("buttons_panel"); + panel->translate(0, -message_delta); } } diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 867d47c893..5b580ef415 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -42,6 +42,7 @@ #include "llcoproceduremanager.h" #include "lleventcoro.h" #include "llsdutil.h" +#include "llstartup.h" #include "llworld.h" ///---------------------------------------------------------------------------- @@ -460,28 +461,78 @@ void LLViewerAssetStorage::assetRequestCoro( if (!gAgent.getRegion()) { - LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; - result_code = LL_ERR_ASSET_REQUEST_FAILED; - ext_status = LLExtStat::NONE; - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); - return; + if (STATE_WORLD_INIT <= LLStartUp::getStartupState()) + { + // Viewer isn't ready, wait for region to become available + LL_INFOS_ONCE("ViewerAsset") << "Waiting for agent region to be set" << LL_ENDL; + + LLEventStream region_init("waitForRegion", true); + std::string pump_name = region_init.getName(); + + boost::signals2::connection region_conn = + gAgent.addRegionChangedCallback([pump_name]() + { + LLEventPumps::instance().obtain(pump_name).post(LLSD()); + }); + F32Seconds timeout_seconds(LL_ASSET_STORAGE_TIMEOUT); + llcoro::suspendUntilEventOnWithTimeout(region_init, timeout_seconds, LLSDMap("timeout", LLSD::Boolean(true))); + gAgent.removeRegionChangedCallback(region_conn); + region_conn.disconnect(); + + if (LLApp::isExiting() || !gAssetStorage) + { + return; + } + + // recheck region whether suspend ended on timeout or not + if (!gAgent.getRegion()) + { + LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: timeout reached while waiting for region" << LL_ENDL; + result_code = LL_ERR_NO_CAP; + ext_status = LLExtStat::NONE; + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); + return; + } + } + else + { + LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; + result_code = LL_ERR_NO_CAP; + ext_status = LLExtStat::NONE; + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); + return; + } } - else if (!gAgent.getRegion()->capabilitiesReceived()) + + if (!gAgent.getRegion()->capabilitiesReceived()) { LL_WARNS_ONCE("ViewerAsset") << "Waiting for capabilities" << LL_ENDL; LLEventStream capsRecv("waitForCaps", true); - gAgent.getRegion()->setCapabilitiesReceivedCallback( - boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, _1, capsRecv.getName())); + boost::signals2::connection caps_conn = + gAgent.getRegion()->setCapabilitiesReceivedCallback( + boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, _1, capsRecv.getName())); - llcoro::suspendUntilEventOn(capsRecv); + F32Seconds timeout_seconds(LL_ASSET_STORAGE_TIMEOUT); // from minutes to seconds, by default 5 minutes + LLSD result = llcoro::suspendUntilEventOnWithTimeout(capsRecv, timeout_seconds, LLSDMap("timeout", LLSD::Boolean(true))); + caps_conn.disconnect(); if (LLApp::isExiting() || !gAssetStorage) { return; } + if (result.has("timeout")) + { + // Caps failed to arrive in 5 minutes + LL_WARNS_ONCE("ViewerAsset") << "Asset " << uuid << " request fails : capabilities took too long to arrive" << LL_ENDL; + result_code = LL_ERR_NO_CAP; + ext_status = LLExtStat::NONE; + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); + return; + } + LL_WARNS_ONCE("ViewerAsset") << "capsRecv got event" << LL_ENDL; LL_WARNS_ONCE("ViewerAsset") << "region " << gAgent.getRegion() << " mViewerAssetUrl " << mViewerAssetUrl << LL_ENDL; } @@ -492,7 +543,7 @@ void LLViewerAssetStorage::assetRequestCoro( if (mViewerAssetUrl.empty()) { LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL; - result_code = LL_ERR_ASSET_REQUEST_FAILED; + result_code = LL_ERR_NO_CAP; ext_status = LLExtStat::NONE; removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); return; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index a8ed79a8cc..6d825441ca 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -814,6 +814,7 @@ void setting_setup_signal_listener(LLControlGroup& group, const std::string& set void settings_setup_listeners() { + LL_PROFILE_ZONE_SCOPED; setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged); setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainScale", handleTerrainScaleChanged); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f29760c824..5799e23ca5 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -140,7 +140,7 @@ #include "llwindow.h" #include "llpathfindingmanager.h" #include "llstartup.h" -#include "boost/unordered_map.hpp" +#include <unordered_map> #include <boost/regex.hpp> #include <boost/algorithm/string.hpp> #include <boost/json.hpp> @@ -153,7 +153,7 @@ using namespace LLAvatarAppearanceDefines; typedef LLPointer<LLViewerObject> LLViewerObjectPtr; -static boost::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels; +static std::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels; LLVOAvatar* find_avatar_from_object(LLViewerObject* object); LLVOAvatar* find_avatar_from_object(const LLUUID& object_id); @@ -413,7 +413,23 @@ static LLSLMMenuUpdater* gSLMMenuUpdater = NULL; LLSLMMenuUpdater::LLSLMMenuUpdater() { - mMarketplaceListingsItem = gMenuHolder->getChild<LLView>("MarketplaceListings")->getHandle(); + LLView* me_menu = gMenuHolder->findChild<LLView>("Me"); + if (!me_menu) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'Me' menu in 'menu_viewer'" << LL_ENDL; + return; + } + + LLView* marketplace_listings = me_menu->findChild<LLView>("MarketplaceListings"); + if (!marketplace_listings) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'MarketplaceListings' in 'Me' menu" << LL_ENDL; + return; + } + + mMarketplaceListingsItem = marketplace_listings->getHandle(); } void LLSLMMenuUpdater::setMerchantMenu() { @@ -473,6 +489,8 @@ void check_merchant_status(bool force) void init_menus() { + LL_PROFILE_ZONE_SCOPED; + // Initialize actions initialize_menus(); @@ -549,7 +567,29 @@ void init_menus() color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); } - LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder"); + LLView* menu_stack = gViewerWindow->getMainView()->findChildView("menu_stack"); + if (!menu_stack) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find menu_stack in main_view" << LL_ENDL; + return; + } + + LLView* status_bar_container = menu_stack->findChildView("status_bar_container"); + if (!status_bar_container) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find status_bar_container in main_view" << LL_ENDL; + return; + } + + LLView* menu_bar_holder = status_bar_container->findChildView("menu_bar_holder"); + if (!menu_bar_holder) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find status_bar_container in main_view" << LL_ENDL; + return; + } gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gMenuBarView->setRect(LLRect(0, menu_bar_holder->getRect().mTop, 0, menu_bar_holder->getRect().mTop - MENU_BAR_HEIGHT)); @@ -563,8 +603,33 @@ void init_menus() // *TODO:Also fix cost in llfolderview.cpp for Inventory menus const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); - gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str); - gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str); + + LLView* main_upload_menu = gMenuHolder->findChild<LLView>("Upload"); + if (!main_upload_menu) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'Upload' menu in 'menu_viewer'" << LL_ENDL; + return; + } + + LLView* upload_sound = main_upload_menu->findChild<LLView>("Upload Sound"); + if (!upload_sound) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'Upload Sound' menu item in 'Upload' menu" << LL_ENDL; + return; + } + upload_sound->setLabelArg("[COST]", sound_upload_cost_str); + + LLView* upload_anim = main_upload_menu->findChild<LLView>("Upload Animation"); + if (!upload_anim) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'Upload Animation' menu item in 'Upload' menu" << LL_ENDL; + return; + } + upload_anim->setLabelArg("[COST]", animation_upload_cost_str); + gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", true); gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", true); @@ -572,13 +637,6 @@ void init_menus() gDetachAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach", true); gDetachHUDAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach HUD", true); - // Don't display the Memory console menu if the feature is turned off - LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", true); - if (memoryMenu) - { - memoryMenu->setVisible(false); - } - gMenuBarView->createJumpKeys(); // Let land based option enable when parcel changes @@ -2963,7 +3021,7 @@ void handle_object_show_original() static void init_default_item_label(LLUICtrl* ctrl) { const std::string& item_name = ctrl->getName(); - boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); + std::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); if (it == sDefaultItemLabels.end()) { // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value @@ -2979,7 +3037,7 @@ static void init_default_item_label(LLUICtrl* ctrl) static LLStringExplicit get_default_item_label(const std::string& item_name) { LLStringExplicit res(""); - boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); + std::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); if (it != sDefaultItemLabels.end()) { res = it->second; @@ -9689,6 +9747,8 @@ void initialize_spellcheck_menu() void initialize_menus() { + LL_PROFILE_ZONE_SCOPED; + // A parameterized event handler used as ctrl-8/9/0 zoom controls below. class LLZoomer : public view_listener_t { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 3a7b721f70..d1e25988cc 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5745,28 +5745,40 @@ void process_script_question(LLMessageSystem *msg, void **user_data) args["NAME"] = clean_owner_name; S32 known_questions = 0; bool has_not_only_debit = questions ^ SCRIPT_PERMISSIONS[SCRIPT_PERMISSION_DEBIT].permbit; + bool caution_enabled = gSavedSettings.getBOOL("PermissionsCautionEnabled"); // check the received permission flags against each permission + std::string warning_msg; for (const script_perm_t& script_perm : SCRIPT_PERMISSIONS) { if (questions & script_perm.permbit) { - count++; known_questions |= script_perm.permbit; // check whether permission question should cause special caution dialog caution |= (script_perm.caution); - if (("ScriptTakeMoney" == script_perm.question) && has_not_only_debit) + // Cautions go into top part of the dialog, questions go into the footer + if (caution_enabled && script_perm.caution) + { + warning_msg += "\n" + LLTrans::getString(script_perm.question + "Caution") + "\n"; continue; + } if (LLTrans::getString(script_perm.question).empty()) { continue; } - script_question += " " + LLTrans::getString(script_perm.question) + "\n"; + count++; + script_question += "\n " + LLTrans::getString(script_perm.question); } } + if (!warning_msg.empty()) + { + LLStringUtil::format(warning_msg, args); + args["WARNINGS"] = warning_msg; + } + args["QUESTIONS"] = script_question; if (known_questions != questions) @@ -5791,12 +5803,12 @@ void process_script_question(LLMessageSystem *msg, void **user_data) // check whether cautions are even enabled or not const char* notification = "ScriptQuestion"; - if(caution && gSavedSettings.getBOOL("PermissionsCautionEnabled")) + if(caution && caution_enabled) { - args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n\n" + script_question : ""; + args["FOOTERTEXT"] = (count > 0) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n" + script_question : ""; notification = "ScriptQuestionCaution"; } - else if(experienceid.notNull()) + else if (experienceid.notNull()) { payload["experience"]=experienceid; LLExperienceCache::instance().get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 0f4cbdd25c..dfb0521167 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -130,6 +130,7 @@ F64Seconds LLViewerObject::sPhaseOutUpdateInterpolationTime(2.0); // For motio F64Seconds LLViewerObject::sMaxRegionCrossingInterpolationTime(1.0);// For motion interpolation: don't interpolate over this time on region crossing std::map<std::string, U32> LLViewerObject::sObjectDataMap; +std::unordered_map<LLUUID, std::vector<LLViewerObject*>> LLViewerObject::sPendingUpdatesByOwner; // The maximum size of an object extra parameters binary (packed) block #define MAX_OBJECT_PARAMS_SIZE 1024 @@ -521,6 +522,8 @@ void LLViewerObject::markDead() mReflectionProbe = nullptr; } + removeObjectFromPendingUpdate(this); + sNumZombieObjects++; } } @@ -7751,6 +7754,61 @@ bool LLViewerObject::isReachable() return false; } +void LLViewerObject::markObjectsForUpdate(const LLUUID& owner_id) +{ + sPendingUpdatesByOwner.erase(owner_id); + for (S32 i = 0; i < gObjectList.getNumObjects(); ++i) + { + LLViewerObject* obj = gObjectList.getObject(i); + if (!obj || obj->isDead() || obj->isAvatar() || obj->permYouOwner()) + { + continue; + } + sPendingUpdatesByOwner[owner_id].push_back(obj); + } +} + +void LLViewerObject::removeObjectFromPendingUpdate(LLViewerObject* obj) +{ + for (auto& [owner_id, objects] : sPendingUpdatesByOwner) + { + objects.erase(std::remove(objects.begin(), objects.end(), obj), objects.end()); + } +} + +bool LLViewerObject::isObjectInPendingUpdate(const LLUUID& owner_id, LLViewerObject* obj) +{ + if (!obj) + { + return false; + } + auto it = sPendingUpdatesByOwner.find(owner_id); + if (it != sPendingUpdatesByOwner.end()) + { + const auto& objects = it->second; + return std::find(objects.begin(), objects.end(), obj) != objects.end(); + } + return false; +} + +void LLViewerObject::requestObjectUpdate() +{ + if (LLViewerRegion* regionp = getRegion()) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RequestMultipleObjects); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU8Fast(_PREHASH_CacheMissType, 0); + msg->addU32Fast(_PREHASH_ID, getLocalID()); + msg->sendReliable(regionp->getHost()); + + removeObjectFromPendingUpdate(this); + } +} + class ObjectPhysicsProperties : public LLHTTPNode { public: diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index cccf59a319..465e221ae4 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -622,6 +622,11 @@ public: void setPhysicsDensity(F32 density); void setPhysicsRestitution(F32 restitution); + static void markObjectsForUpdate(const LLUUID& owner_id); + static void removeObjectFromPendingUpdate(LLViewerObject* obj); + static bool isObjectInPendingUpdate(const LLUUID& owner_id, LLViewerObject* obj); + void requestObjectUpdate(); + virtual void dump() const; static U32 getNumZombieObjects() { return sNumZombieObjects; } @@ -796,6 +801,7 @@ private: std::unique_ptr<LLReflectionProbeParams> mReflectionProbeParams; static std::map<std::string, U32> sObjectDataMap; + static std::unordered_map<LLUUID, std::vector<LLViewerObject*>> sPendingUpdatesByOwner; public: // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties U8 mPhysicsShapeType; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 50edb408c7..34e5cc9de8 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -174,7 +174,7 @@ bool LLViewerObjectList::removeFromLocalIDTable(LLViewerObject* objectp) U32 local_id = objectp->mLocalID; U64 indexid = (((U64)objectp->mRegionIndex) << 32) | (U64)local_id; - std::map<U64, LLUUID>::iterator iter = mIndexAndLocalIDToUUID.find(indexid); + auto iter = mIndexAndLocalIDToUUID.find(indexid); if (iter == mIndexAndLocalIDToUUID.end()) { return false; diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 547ef9fb2d..adc90a0483 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -204,7 +204,7 @@ protected: uuid_set_t mDeadObjects; - std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap; + std::unordered_map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap; //set of objects that need to update their cost uuid_set_t mStaleObjectCost; @@ -221,7 +221,7 @@ protected: static U32 sSimulatorMachineIndex; std::map<U64, U32> mIPAndPortToIndex; - std::map<U64, LLUUID> mIndexAndLocalIDToUUID; + std::unordered_map<U64, LLUUID> mIndexAndLocalIDToUUID; friend class LLViewerObject; diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index f6ee00cb25..d33d426769 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -126,8 +126,6 @@ #include "llfloater.h" #include <boost/signals2.hpp> -#include <boost/unordered_set.hpp> -#include <boost/unordered_map.hpp> #include <boost/json.hpp> #include "glm/glm.hpp" diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index cd70f8f9b9..42a587f376 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -104,7 +104,7 @@ S32 LLViewerRegion::sLastCameraUpdated = 0; S32 LLViewerRegion::sNewObjectCreationThrottle = -1; LLViewerRegion::vocache_entry_map_t LLViewerRegion::sRegionCacheCleanup; -typedef std::map<std::string, std::string> CapabilityMap; +typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> CapabilityMap; static void log_capabilities(const CapabilityMap &capmap); @@ -3437,7 +3437,7 @@ void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::stri } } -std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const +std::string LLViewerRegion::getCapabilityDebug(std::string_view name) const { CapabilityMap::const_iterator iter = mImpl->mSecondCapabilitiesTracker.find(name); if (iter == mImpl->mSecondCapabilitiesTracker.end()) @@ -3448,15 +3448,14 @@ std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const return iter->second; } - -bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) +bool LLViewerRegion::isSpecialCapabilityName(std::string_view name) { return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; } -std::string LLViewerRegion::getCapability(const std::string& name) const +std::string LLViewerRegion::getCapability(std::string_view name) const { - if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) + if (!capabilitiesReceived() && (name != "Seed") && (name != "ObjectMedia")) { LL_WARNS() << "getCapability called before caps received for " << name << LL_ENDL; } @@ -3464,21 +3463,20 @@ std::string LLViewerRegion::getCapability(const std::string& name) const CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); if(iter == mImpl->mCapabilities.end()) { - return ""; + return {}; } return iter->second; } -bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const +bool LLViewerRegion::isCapabilityAvailable(std::string_view name) const { - if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) + if (!capabilitiesReceived() && (name != "Seed") && (name != "ObjectMedia")) { LL_WARNS() << "isCapabilityAvailable called before caps received for " << name << LL_ENDL; } - CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); - if(iter == mImpl->mCapabilities.end()) + if (!mImpl->mCapabilities.contains(name)) { return false; } @@ -3734,9 +3732,14 @@ bool LLViewerRegion::avatarHoverHeightEnabled() const void log_capabilities(const CapabilityMap &capmap) { + // Copy into sorted map for ordered output + using SortedCapabilityMap = std::map<std::string, std::string>; + SortedCapabilityMap sorted_capmap; + sorted_capmap.insert(capmap.begin(), capmap.end()); + S32 count = 0; - CapabilityMap::const_iterator iter; - for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count) + SortedCapabilityMap::const_iterator iter; + for (iter = sorted_capmap.begin(); iter != sorted_capmap.end(); ++iter, ++count) { if (!iter->second.empty()) { diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index b3ec857907..974bc375b8 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -274,10 +274,10 @@ public: S32 getNumSeedCapRetries(); void setCapability(const std::string& name, const std::string& url); void setCapabilityDebug(const std::string& name, const std::string& url); - bool isCapabilityAvailable(const std::string& name) const; + bool isCapabilityAvailable(std::string_view name) const; // implements LLCapabilityProvider - virtual std::string getCapability(const std::string& name) const; - std::string getCapabilityDebug(const std::string& name) const; + virtual std::string getCapability(std::string_view name) const; + std::string getCapabilityDebug(std::string_view name) const; // has region received its final (not seed) capability list? @@ -287,7 +287,7 @@ public: void setCapabilitiesError(); boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb); - static bool isSpecialCapabilityName(const std::string &name); + static bool isSpecialCapabilityName(std::string_view name); void logActiveCapabilities() const; // Utilities to post and get via diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 1e83482752..23915d01fa 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1488,7 +1488,9 @@ bool LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/) // from local images, but this might become unsafe in case of changes to fetcher if (mBoostLevel == BOOST_PREVIEW) { - mRawImage->biasedScaleToPowerOfTwo(1024); + // A local file with a preview flag likely means mesh's texture upload + // which should follow normal upload scaling rules + mRawImage->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); } else { // leave black border, do not scale image content @@ -2574,14 +2576,31 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() S32 best_raw_discard = gl_discard; // Current GL quality level S32 current_aux_discard = MAX_DISCARD_LEVEL + 1; S32 best_aux_discard = MAX_DISCARD_LEVEL + 1; + LLImageRaw *current_raw_image = nullptr; if (mIsRawImageValid) { - // If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels. + // If we have an existing raw image, we have a baseline for the raw + // and auxiliary quality levels. + // Note: we call updateImagesCreateTextures before callbacks, which + // leads to destroyRawImage and deletes raw image. So this case + // might be rare or even never trigger as there is never a raw image, + // only a saved one. current_raw_discard = mRawDiscardLevel; best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel); best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw current_aux_discard = llmin(current_aux_discard, best_aux_discard); + current_raw_image = mRawImage; + } + else if (mSavedRawImage.notNull()) + { + // We have a saved raw image, we can use that as our baseline for + // raw and auxiliary quality levels. + current_raw_discard = mSavedRawDiscardLevel; + best_raw_discard = llmin(best_raw_discard, mSavedRawDiscardLevel); + best_aux_discard = llmin(best_aux_discard, mSavedRawDiscardLevel); // We always decode the aux when we decode the base raw + current_aux_discard = llmin(current_aux_discard, best_aux_discard); + current_raw_image = mSavedRawImage; } else { @@ -2646,12 +2665,17 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() if (need_readback) { readbackRawImage(); + if (mIsRawImageValid) + { + current_raw_discard = mRawDiscardLevel; + current_raw_image = mRawImage; + } } // // Run raw/auxiliary data callbacks // - if (run_raw_callbacks && mIsRawImageValid && (mRawDiscardLevel <= getMaxDiscardLevel())) + if (run_raw_callbacks && current_raw_image != nullptr && (current_raw_discard <= getMaxDiscardLevel())) { // Do callbacks which require raw image data. //LL_INFOS() << "doLoadedCallbacks raw for " << getID() << LL_ENDL; @@ -2662,7 +2686,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() { callback_list_t::iterator curiter = iter++; LLLoadedCallbackEntry *entryp = *curiter; - if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > mRawDiscardLevel)) + if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > current_raw_discard)) { // If we've loaded all the data there is to load or we've loaded enough // to satisfy the interested party, then this is the last time that @@ -2673,11 +2697,11 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() { LL_WARNS() << "Raw Image with no Aux Data for callback" << LL_ENDL; } - bool final = mRawDiscardLevel <= entryp->mDesiredDiscard; + bool final = current_raw_discard <= entryp->mDesiredDiscard; //LL_INFOS() << "Running callback for " << getID() << LL_ENDL; - //LL_INFOS() << mRawImage->getWidth() << "x" << mRawImage->getHeight() << LL_ENDL; - entryp->mLastUsedDiscard = mRawDiscardLevel; - entryp->mCallback(true, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData); + //LL_INFOS() << current_raw_image->getWidth() << "x" << current_raw_image->getHeight() << LL_ENDL; + entryp->mLastUsedDiscard = current_raw_discard; + entryp->mCallback(true, this, current_raw_image, mAuxRawImage, current_raw_discard, final, entryp->mUserData); if (final) { iter = mLoadedCallbackList.erase(curiter); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a3c241456d..773ff14e90 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2067,10 +2067,6 @@ void LLViewerWindow::initGLDefaults() gBox.prerender(); } -struct MainPanel : public LLPanel -{ -}; - void LLViewerWindow::initBase() { S32 height = getWindowHeightScaled(); @@ -2109,6 +2105,8 @@ void LLViewerWindow::initBase() main_view->setShape(full_window); getRootView()->addChild(main_view); + mMainView = main_view; + // placeholder widget that controls where "world" is rendered mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle(); mPopupView = main_view->getChild<LLPopupView>("popup_holder"); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 9a0bb28f1d..105c1b8baa 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -144,6 +144,10 @@ private: }; +struct MainPanel : public LLPanel +{ +}; + static const U32 MAX_SNAPSHOT_IMAGE_SIZE = 7680; // max snapshot image size 7680 * 7680 UHDTV2 class LLViewerWindow : public LLWindowCallbacks @@ -248,6 +252,7 @@ public: // ACCESSORS // LLRootView* getRootView() const; + MainPanel* getMainView() const { return mMainView; } // 3D world area in scaled pixels (via UI scale), use for most UI computations LLRect getWorldViewRectScaled() const; @@ -500,6 +505,7 @@ private: LLRect mWorldViewRectRaw; // area of screen for 3D world LLRect mWorldViewRectScaled; // area of screen for 3D world scaled by UI size LLRootView* mRootView; // a view of size mWindowRectRaw, containing all child views + MainPanel* mMainView; // a view of size mWindowRectRaw, directly containing the base elements of the ui tree LLView* mFloaterSnapRegion = nullptr; LLView* mNavBarContainer = nullptr; LLPanel* mStatusBarContainer = nullptr; diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index d1de2f55da..481f9e3522 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -2496,17 +2496,18 @@ void LLVoiceWebRTCConnection::processIceUpdatesCoro(connectionPtr_t connection) // callback from llwebrtc void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp) { + connectionPtr_t connection = shared_from_this(); LL::WorkQueue::postMaybe(mMainQueue, - [=, this] { - if (mShutDown) + [=] { + if (connection->mShutDown) { return; } LL_DEBUGS("Voice") << "On Offer Available." << LL_ENDL; - mChannelSDP = sdp; - if (mVoiceConnectionState == VOICE_STATE_WAIT_FOR_SESSION_START) + connection->mChannelSDP = sdp; + if (connection->mVoiceConnectionState == VOICE_STATE_WAIT_FOR_SESSION_START) { - mVoiceConnectionState = VOICE_STATE_REQUEST_CONNECTION; + connection->mVoiceConnectionState = VOICE_STATE_REQUEST_CONNECTION; } }); } @@ -2523,16 +2524,17 @@ void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp) // callback from llwebrtc void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface* audio_interface) { + connectionPtr_t connection = shared_from_this(); LL::WorkQueue::postMaybe(mMainQueue, - [=, this] { - if (mShutDown) + [=] { + if (connection->mShutDown) { return; } LL_DEBUGS("Voice") << "On AudioEstablished." << LL_ENDL; - mWebRTCAudioInterface = audio_interface; - mWebRTCAudioInterface->setMute(true); // mute will be set appropriately later when we finish setting up. - setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED); + connection->mWebRTCAudioInterface = audio_interface; + connection->mWebRTCAudioInterface->setMute(true); // mute will be set appropriately later when we finish setting up. + connection->setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED); }); } @@ -3207,17 +3209,18 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b // llwebrtc callback void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) { + connectionPtr_t connection = shared_from_this(); LL::WorkQueue::postMaybe(mMainQueue, - [=, this] { - if (mShutDown) + [=] { + if (connection->mShutDown) { return; } if (data_interface) { - mWebRTCDataInterface = data_interface; - mWebRTCDataInterface->setDataObserver(this); + connection->mWebRTCDataInterface = data_interface; + connection->mWebRTCDataInterface->setDataObserver(connection.get()); } }); } diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp deleted file mode 100644 index 072743505f..0000000000 --- a/indra/newview/llwatchdog.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/** - * @file llthreadwatchdog.cpp - * @brief The LLThreadWatchdog class definitions - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - - -#include "llviewerprecompiledheaders.h" -#include "llwatchdog.h" -#include "llmutex.h" -#include "llthread.h" -#include "llappviewer.h" - -constexpr U32 WATCHDOG_SLEEP_TIME_USEC = 1000000U; - -// This class runs the watchdog timing thread. -class LLWatchdogTimerThread : public LLThread -{ -public: - LLWatchdogTimerThread() : - LLThread("Watchdog"), - mSleepMsecs(0), - mStopping(false) - { - } - - ~LLWatchdogTimerThread() {} - - void setSleepTime(long ms) { mSleepMsecs = ms; } - void stop() - { - mStopping = true; - mSleepMsecs = 1; - } - - void run() override - { - while(!mStopping) - { - LLWatchdog::getInstance()->run(); - ms_sleep(mSleepMsecs); - } - } - -private: - long mSleepMsecs; - bool mStopping; -}; - -// LLWatchdogEntry -LLWatchdogEntry::LLWatchdogEntry() -{ -} - -LLWatchdogEntry::~LLWatchdogEntry() -{ - stop(); -} - -void LLWatchdogEntry::start() -{ - LLWatchdog::getInstance()->add(this); -} - -void LLWatchdogEntry::stop() -{ - // this can happen very late in the shutdown sequence - if (!LLWatchdog::wasDeleted()) - { - LLWatchdog::getInstance()->remove(this); - } -} - -// LLWatchdogTimeout -const std::string UNINIT_STRING = "uninitialized"; - -LLWatchdogTimeout::LLWatchdogTimeout() : - mTimeout(0.0f), - mPingState(UNINIT_STRING) -{ -} - -LLWatchdogTimeout::~LLWatchdogTimeout() -{ -} - -bool LLWatchdogTimeout::isAlive() const -{ - return (mTimer.getStarted() && !mTimer.hasExpired()); -} - -void LLWatchdogTimeout::reset() -{ - mTimer.setTimerExpirySec(mTimeout); -} - -void LLWatchdogTimeout::setTimeout(F32 d) -{ - mTimeout = d; -} - -void LLWatchdogTimeout::start(std::string_view state) -{ - if (mTimeout == 0) - { - LL_WARNS() << "Cant' start watchdog entry - no timeout set" << LL_ENDL; - return; - } - // Order of operation is very important here. - // After LLWatchdogEntry::start() is called - // LLWatchdogTimeout::isAlive() will be called asynchronously. - ping(state); - mTimer.start(); - mTimer.setTimerExpirySec(mTimeout); // timer expiration set to 0 by start() - LLWatchdogEntry::start(); -} - -void LLWatchdogTimeout::stop() -{ - LLWatchdogEntry::stop(); - mTimer.stop(); -} - -void LLWatchdogTimeout::ping(std::string_view state) -{ - if (!state.empty()) - { - mPingState = state; - } - reset(); -} - -// LLWatchdog -LLWatchdog::LLWatchdog() - :mSuspectsAccessMutex() - ,mTimer(nullptr) - ,mLastClockCount(0) -{ -} - -LLWatchdog::~LLWatchdog() -{ -} - -void LLWatchdog::add(LLWatchdogEntry* e) -{ - lockThread(); - mSuspects.insert(e); - unlockThread(); -} - -void LLWatchdog::remove(LLWatchdogEntry* e) -{ - lockThread(); - mSuspects.erase(e); - unlockThread(); -} - -void LLWatchdog::init() -{ - if (!mSuspectsAccessMutex && !mTimer) - { - mSuspectsAccessMutex = new LLMutex(); - mTimer = new LLWatchdogTimerThread(); - mTimer->setSleepTime(WATCHDOG_SLEEP_TIME_USEC / 1000); - mLastClockCount = LLTimer::getTotalTime(); - - // mTimer->start() kicks off the thread, any code after - // start needs to use the mSuspectsAccessMutex - mTimer->start(); - } -} - -void LLWatchdog::cleanup() -{ - if (mTimer) - { - mTimer->stop(); - delete mTimer; - mTimer = nullptr; - } - - if (mSuspectsAccessMutex) - { - delete mSuspectsAccessMutex; - mSuspectsAccessMutex = nullptr; - } - - mLastClockCount = 0; -} - -void LLWatchdog::run() -{ - lockThread(); - - // Check the time since the last call to run... - // If the time elapsed is two times greater than the regualr sleep time - // reset the active timeouts. - constexpr U32 TIME_ELAPSED_MULTIPLIER = 2; - U64 current_time = LLTimer::getTotalTime(); - U64 current_run_delta = current_time - mLastClockCount; - mLastClockCount = current_time; - - if (current_run_delta > (WATCHDOG_SLEEP_TIME_USEC * TIME_ELAPSED_MULTIPLIER)) - { - LL_INFOS() << "Watchdog thread delayed: resetting entries." << LL_ENDL; - for (const auto& suspect : mSuspects) - { - suspect->reset(); - } - } - else - { - SuspectsRegistry::iterator result = - std::find_if(mSuspects.begin(), - mSuspects.end(), - [](const LLWatchdogEntry* suspect){ return ! suspect->isAlive(); }); - if (result != mSuspects.end()) - { - // error!!! - if(mTimer) - { - mTimer->stop(); - } - if (LLAppViewer::instance()->logoutRequestSent()) - { - LLAppViewer::instance()->createErrorMarker(LAST_EXEC_LOGOUT_FROZE); - } - else - { - LLAppViewer::instance()->createErrorMarker(LAST_EXEC_FROZE); - } - // Todo1: warn user? - // Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'. - LL_ERRS() << "Watchdog timer expired; assuming viewer is hung and crashing" << LL_ENDL; - } - } - - - unlockThread(); -} - -void LLWatchdog::lockThread() -{ - if (mSuspectsAccessMutex) - { - mSuspectsAccessMutex->lock(); - } -} - -void LLWatchdog::unlockThread() -{ - if (mSuspectsAccessMutex) - { - mSuspectsAccessMutex->unlock(); - } -} diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h deleted file mode 100644 index b7dd55577e..0000000000 --- a/indra/newview/llwatchdog.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file llthreadwatchdog.h - * @brief The LLThreadWatchdog class declaration - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLTHREADWATCHDOG_H -#define LL_LLTHREADWATCHDOG_H - -#ifndef LL_TIMER_H - #include "lltimer.h" -#endif - -// LLWatchdogEntry is the interface used by the tasks that -// need to be watched. -class LLWatchdogEntry -{ -public: - LLWatchdogEntry(); - virtual ~LLWatchdogEntry(); - - // isAlive is accessed by the watchdog thread. - // This may mean that resources used by - // isAlive and other method may need synchronization. - virtual bool isAlive() const = 0; - virtual void reset() = 0; - virtual void start(); - virtual void stop(); -}; - -class LLWatchdogTimeout : public LLWatchdogEntry -{ -public: - LLWatchdogTimeout(); - virtual ~LLWatchdogTimeout(); - - bool isAlive() const override; - void reset() override; - void start() override { start(""); } - void stop() override; - - void start(std::string_view state); - void setTimeout(F32 d); - void ping(std::string_view state); - const std::string& getState() {return mPingState; } - -private: - LLTimer mTimer; - F32 mTimeout; - std::string mPingState; -}; - -class LLWatchdogTimerThread; // Defined in the cpp -class LLWatchdog : public LLSingleton<LLWatchdog> -{ - LLSINGLETON(LLWatchdog); - ~LLWatchdog(); - -public: - // Add an entry to the watchdog. - void add(LLWatchdogEntry* e); - void remove(LLWatchdogEntry* e); - - void init(); - void run(); - void cleanup(); - -private: - void lockThread(); - void unlockThread(); - - typedef std::set<LLWatchdogEntry*> SuspectsRegistry; - SuspectsRegistry mSuspects; - LLMutex* mSuspectsAccessMutex; - LLWatchdogTimerThread* mTimer; - U64 mLastClockCount; -}; - -#endif // LL_LLTHREADWATCHDOG_H diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index cc593fe7b4..f639024228 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -82,7 +82,7 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item, co ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(&typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item"); LLPanelWearableOutfitItem::Params::Params() : add_btn("add_btn"), @@ -222,7 +222,7 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelClothingListItem(&typeid(LLPanelClothingListItem::Params), "clothing_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelClothingListItem(typeid(LLPanelClothingListItem::Params), "clothing_list_item"); LLPanelClothingListItem::Params::Params() @@ -309,7 +309,7 @@ bool LLPanelClothingListItem::postBuild() ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelBodyPartsListItem(&typeid(LLPanelBodyPartsListItem::Params), "bodyparts_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelBodyPartsListItem(typeid(LLPanelBodyPartsListItem::Params), "bodyparts_list_item"); LLPanelBodyPartsListItem::Params::Params() @@ -380,7 +380,7 @@ bool LLPanelBodyPartsListItem::postBuild() return true; } -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDeletableWearableListItem(&typeid(LLPanelDeletableWearableListItem::Params), "deletable_wearable_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDeletableWearableListItem(typeid(LLPanelDeletableWearableListItem::Params), "deletable_wearable_list_item"); LLPanelDeletableWearableListItem::Params::Params() : delete_btn("delete_btn") @@ -467,7 +467,7 @@ void LLPanelAttachmentListItem::updateItem(const std::string& name, ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDummyClothingListItem(&typeid(LLPanelDummyClothingListItem::Params), "dummy_clothing_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDummyClothingListItem(typeid(LLPanelDummyClothingListItem::Params), "dummy_clothing_list_item"); LLPanelDummyClothingListItem::Params::Params() : add_panel("add_panel"), diff --git a/indra/newview/skins/default/xui/en/menu_favorites.xml b/indra/newview/skins/default/xui/en/menu_favorites.xml index 6345394b46..f82f705fb7 100644 --- a/indra/newview/skins/default/xui/en/menu_favorites.xml +++ b/indra/newview/skins/default/xui/en/menu_favorites.xml @@ -35,6 +35,9 @@ <menu_item_call.on_click function="Favorites.DoToSelected" parameter="show_on_map" /> + <menu_item_call.on_enable + function="Favorites.EnableSelected" + parameter="show_on_map" /> </menu_item_call> <menu_item_call label="Copy SLurl" @@ -43,6 +46,9 @@ <menu_item_call.on_click function="Favorites.DoToSelected" parameter="copy_slurl" /> + <menu_item_call.on_enable + function="Favorites.EnableSelected" + parameter="copy_slurl" /> </menu_item_call> <menu_item_call label="Create Pick" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index c93cb7822e..ba43e80eda 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2601,18 +2601,6 @@ function="World.EnvPreset" parameter="fast timers" /> </menu_item_check> <menu_item_check - label="Memory" - name="Memory" - shortcut="control|shift|0" - use_mac_ctrl="true"> - <menu_item_check.on_check - function="Advanced.CheckConsole" - parameter="memory view" /> - <menu_item_check.on_click - function="Advanced.ToggleConsole" - parameter="memory view" /> - </menu_item_check> - <menu_item_check label="Scene Statistics" name="Scene Statistics"> <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d278bac075..59deead084 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2466,6 +2466,17 @@ You already have a landmark for this location. </notification> <notification + icon="alert.tga" + name="LandmarkLocationUnknown" + type="alert"> +Viewer wasn't able to get region's location. Region might be temporarily unavailable, was removed or landmark failed to load. + <usetemplate + name="okbutton" + yestext="OK"/> + <tag>fail</tag> + </notification> + + <notification icon="alertmodal.tga" name="CannotCreateLandmarkNotOwner" type="alertmodal"> @@ -8585,10 +8596,10 @@ Scripts associated with this experience will be able to do the following on regi priority="critical" persist="true" type="notify"> -Warning: The object '<nolink>[OBJECTNAME]</nolink>' wants total access to your Linden Dollars account. If you allow access, it can remove funds from your account at any time, or empty your account completely, on an ongoing basis with no additional warnings. - -Do not allow access if you do not fully understand why it wants access to your account. +Warning: +[WARNINGS] +Do not allow access if you do not fully understand why it wants access to your account. <tag>confirm</tag> <form name="form"> <button @@ -8601,9 +8612,7 @@ Do not allow access if you do not fully understand why it wants access to your a name="Deny" text="Deny"/> </form> - <footer> -[FOOTERTEXT] - </footer> + <footer>[FOOTERTEXT]</footer> </notification> <notification diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index bfe738f472..eaf638d35f 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -49,7 +49,7 @@ embedded_items="false" enabled="false" follows="left|right|top|bottom" - height="85" + height="85" layout="topleft" left="10" mouse_opaque="false" @@ -67,16 +67,16 @@ <panel background_visible="false" follows="left|right|bottom" - height="30" + height="30" width="290" label="control_panel" layout="topleft" left="10" name="control_panel" top_pad="5"> - <!-- + <!-- Notes: - This panel holds buttons of notification. Change of its size can affect the layout of buttons. + This panel holds buttons of notification. Change of its size can affect the layout of buttons. --> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_script_question_toast.xml b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml index 1b1e31165a..9045e6a8ae 100644 --- a/indra/newview/skins/default/xui/en/panel_script_question_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml @@ -6,7 +6,7 @@ bg_alpha_color="PanelNotificationBackground" bg_opaque_color="PanelNotificationBackground" chrome="true" - height="270" + height="220" label="script_question_panel" layout="topleft" left="0" @@ -39,9 +39,9 @@ width="285"> </panel> <text - follows="all" + follows="left|right|top" font="SansSerifBold" - height="55" + height="15" layout="topleft" mouse_opaque="false" name="bottom_info_message" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 8e0eea97d1..1860d38b0e 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -518,6 +518,8 @@ http://secondlife.com/support for help fixing this problem. <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string> <string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string> <string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string> + <string name="ScriptTakeMoneyCaution">The object '<nolink>[OBJECTNAME]</nolink>' wants total access to your Linden Dollars account. If you allow access, it can remove funds from your account at any time, or empty your account completely, on an ongoing basis with no additional warnings.</string> + <string name="PrivilegedLandAccessCaution">The object '<nolink>[OBJECTNAME]</nolink>' wants privileged access to your land. If you allow access it may sell your land with no additional warnings.</string> <string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string> <string name="ScriptTakeMoney">Take Linden dollars (L$) from you</string> <string name="ActOnControlInputs">Act on your control inputs</string> @@ -535,6 +537,7 @@ http://secondlife.com/support for help fixing this problem. <string name="ChangeYourDefaultAnimations">Change your default animations</string> <string name="ForceSitAvatar">Force your avatar to sit</string> <string name="ChangeEnvSettings">Change your environment settings</string> + <string name="PrivilegedLandAccess">Sell land on your behalf.</string> <string name="NotConnected">Not Connected</string> <string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp index acbf019034..3e2e5e70a2 100644 --- a/indra/newview/tests/lldateutil_test.cpp +++ b/indra/newview/tests/lldateutil_test.cpp @@ -34,16 +34,16 @@ #include "lltrans.h" #include "llui.h" -#include <map> +#include <unordered_map> // Baked-in return values for getString() -std::map< std::string, std::string, std::less<>> gString; +std::unordered_map< std::string, std::string, ll::string_hash, std::equal_to<>> gString; // Baked-in return values for getCountString() // map of pairs of input xml_desc and integer count typedef std::pair< std::string, int > count_string_t; -std::map< count_string_t, std::string > gCountString; +std::map<count_string_t, std::string> gCountString; std::string LLTrans::getString(const std::string_view xml_desc, const LLStringUtil::format_map_t& args, bool def_string) { diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 273ffab84f..bcabc07c5a 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -259,9 +259,10 @@ class ViewerManifest(LLManifest): global CHANNEL_VENDOR_BASE channel_type=self.channel_type() if channel_type == 'release': - return CHANNEL_VENDOR_BASE + app_suffix='Viewer' else: - return CHANNEL_VENDOR_BASE + ' ' + self.channel_variant() + app_suffix=self.channel_variant() + return CHANNEL_VENDOR_BASE + ' ' + app_suffix def exec_name(self): return "SecondLifeViewer" |
