diff options
| -rw-r--r-- | indra/newview/llagentwearables.cpp | 10 | ||||
| -rw-r--r-- | indra/newview/llappearancemgr.cpp | 2 | ||||
| -rwxr-xr-x | indra/newview/llfloaterworldmap.cpp | 9 | ||||
| -rw-r--r-- | indra/newview/llimprocessing.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llmutelist.cpp | 50 | ||||
| -rw-r--r-- | indra/newview/llmutelist.h | 14 | ||||
| -rw-r--r-- | indra/newview/lloutfitslist.cpp | 24 | ||||
| -rw-r--r-- | indra/newview/llpanelemojicomplete.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llpanelface.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.cpp | 54 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.h | 5 | ||||
| -rw-r--r-- | indra/newview/llvoavatarself.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llvoavatarself.h | 2 | ||||
| -rw-r--r-- | indra/newview/tests/llviewerassetstats_test.cpp | 5 |
14 files changed, 140 insertions, 50 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index cd4222dddf..25f5cbd78f 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1094,12 +1094,12 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it { gAgentAvatarp->setCompositeUpdatesEnabled(true); - // If we have not yet declouded, we may want to use + // If we have not yet loaded core parts, we may want to use // baked texture UUIDs sent from the first objectUpdate message - // don't overwrite these. If we have already declouded, we've saved - // these ids as the last known good textures and can invalidate without - // re-clouding. - if (!gAgentAvatarp->getIsCloud()) + // don't overwrite these. If we have parts already, we've saved + // these texture ids as the last known good textures and can + // invalidate without having to recloud avatar. + if (!gAgentAvatarp->getHasMissingParts()) { gAgentAvatarp->invalidateAll(); } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e9d455ae53..8a17ccfeef 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -856,7 +856,7 @@ void LLWearableHoldingPattern::checkMissingWearables() // was requested but none was found, create a default asset as a replacement. // In all other cases, don't do anything. // For critical types (shape/hair/skin/eyes), this will keep the avatar as a cloud - // due to logic in LLVOAvatarSelf::getIsCloud(). + // due to logic in LLVOAvatarSelf::getHasMissingParts(). // For non-critical types (tatoo, socks, etc.) the wearable will just be missing. (requested_by_type[type] > 0) && ((type == LLWearableType::WT_PANTS) || (type == LLWearableType::WT_SHIRT) || (type == LLWearableType::WT_SKIRT))) diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index c70058145a..565642e683 100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -1694,14 +1694,15 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) if (!match.isUndefined()) { mSearchResults->selectByValue(match); + mSearchResults->setFocus(true); + onCommitSearchResult(); } - // else select first found item + // else let user decide else { - mSearchResults->selectFirstItem(); + mSearchResults->operateOnAll(LLCtrlListInterface::OP_DESELECT); + mSearchResults->setFocus(true); } - mSearchResults->setFocus(true); - onCommitSearchResult(); } else { diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 4c02511268..7cd0171a37 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -1520,10 +1520,10 @@ void LLIMProcessing::requestOfflineMessages() if (!requested && gMessageSystem && !gDisconnected - && LLMuteList::getInstance()->isLoaded() && isAgentAvatarValid() && gAgent.getRegion() - && gAgent.getRegion()->capabilitiesReceived()) + && gAgent.getRegion()->capabilitiesReceived() + && (LLMuteList::getInstance()->isLoaded() || LLMuteList::getInstance()->getLoadFailed())) { std::string cap_url = gAgent.getRegionCapability("ReadOfflineMsgs"); diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 2d51acc063..f6d635f51f 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -154,7 +154,8 @@ std::string LLMute::getDisplayType() const // LLMuteList() //----------------------------------------------------------------------------- LLMuteList::LLMuteList() : - mIsLoaded(false) + mLoadState(ML_INITIAL), + mRequestStartTime(0.f) { gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList); @@ -209,6 +210,23 @@ bool LLMuteList::isLinden(const std::string& name) return last_name == "linden"; } +bool LLMuteList::getLoadFailed() const +{ + if (mLoadState == ML_FAILED) + { + return true; + } + if (mLoadState == ML_REQUESTED) + { + constexpr F64 WAIT_SECONDS = 30; + if (mRequestStartTime + WAIT_SECONDS < LLTimer::getTotalSeconds()) + { + return true; + } + } + return false; +} + static LLVOAvatar* find_avatar(const LLUUID& id) { LLViewerObject *obj = gObjectList.findObject(id); @@ -371,11 +389,14 @@ void LLMuteList::updateAdd(const LLMute& mute) msg->addU32("MuteFlags", mute.mFlags); gAgent.sendReliableMessage(); - if (!mIsLoaded) + if (!isLoaded()) { LL_WARNS() << "Added elements to non-initialized block list" << LL_ENDL; } - mIsLoaded = true; // why is this here? -MG + // Based of logs and testing, if file doesn't exist server side, + // viewer will not receive any callback and won't know to set + // ML_LOADED. As a workaround, set it regardless of current state. + mLoadState = ML_LOADED; } @@ -564,6 +585,7 @@ bool LLMuteList::loadFromFile(const std::string& filename) if(!filename.size()) { LL_WARNS() << "Mute List Filename is Empty!" << LL_ENDL; + mLoadState = ML_FAILED; return false; } @@ -571,6 +593,7 @@ bool LLMuteList::loadFromFile(const std::string& filename) if (!fp) { LL_WARNS() << "Couldn't open mute list " << filename << LL_ENDL; + mLoadState = ML_FAILED; return false; } @@ -730,13 +753,17 @@ void LLMuteList::requestFromServer(const LLUUID& agent_id) if (gDisconnected) { LL_WARNS() << "Trying to request mute list when disconnected!" << LL_ENDL; + mLoadState = ML_FAILED; return; } if (!gAgent.getRegion()) { LL_WARNS() << "No region for agent yet, skipping mute list request!" << LL_ENDL; + mLoadState = ML_FAILED; return; } + mLoadState = ML_REQUESTED; + mRequestStartTime = LLTimer::getElapsedSeconds(); // Double amount of retries due to this request happening during busy stage // Ideally this should be turned into a capability gMessageSystem->sendReliable(gAgent.getRegionHost(), LL_DEFAULT_RELIABLE_RETRIES * 2, true, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL); @@ -749,7 +776,7 @@ void LLMuteList::requestFromServer(const LLUUID& agent_id) void LLMuteList::cache(const LLUUID& agent_id) { // Write to disk even if empty. - if(mIsLoaded) + if(isLoaded()) { std::string agent_id_string; std::string filename; @@ -777,6 +804,13 @@ void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**) msg->getStringFast(_PREHASH_MuteData, _PREHASH_Filename, unclean_filename); std::string filename = LLDir::getScrubbedFileName(unclean_filename); + LLMuteList* mute_list = getInstance(); + mute_list->mLoadState = ML_REQUESTED; + mute_list->mRequestStartTime = LLTimer::getElapsedSeconds(); + + // Todo: Based of logs and testing, there is no callback + // from server if file doesn't exist server side. + // Once server side gets fixed make sure it gets handled right. std::string *local_filename_and_path = new std::string(gDirUtilp->getExpandedFilename( LL_PATH_CACHE, filename )); gXferManager->requestFile(*local_filename_and_path, filename, @@ -809,12 +843,16 @@ void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_ LLMuteList::getInstance()->loadFromFile(*local_filename_and_path); LLFile::remove(*local_filename_and_path); } + else + { + LLMuteList::getInstance()->mLoadState = ML_FAILED; + } delete local_filename_and_path; } void LLMuteList::onAccountNameChanged(const LLUUID& id, const std::string& username) { - if (mIsLoaded) + if (isLoaded()) { LLMute mute(id, username, LLMute::AGENT); mute_set_t::iterator mute_it = mMutes.find(mute); @@ -866,7 +904,7 @@ void LLMuteList::removeObserver(LLMuteListObserver* observer) void LLMuteList::setLoaded() { - mIsLoaded = true; + mLoadState = ML_LOADED; notifyObservers(); } diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 13d579c61f..b65fd61fcc 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -74,6 +74,14 @@ class LLMuteList : public LLSingleton<LLMuteList> LLSINGLETON(LLMuteList); ~LLMuteList(); /*virtual*/ void cleanupSingleton() override; + + enum EMuteListState + { + ML_INITIAL, + ML_REQUESTED, + ML_LOADED, + ML_FAILED, + }; public: // reasons for auto-unmuting a resident enum EAutoReason @@ -107,7 +115,8 @@ public: static bool isLinden(const std::string& name); - bool isLoaded() const { return mIsLoaded; } + bool isLoaded() const { return mLoadState == ML_LOADED; } + bool getLoadFailed() const; std::vector<LLMute> getMutes() const; @@ -167,7 +176,8 @@ private: typedef std::set<LLMuteListObserver*> observer_set_t; observer_set_t mObservers; - bool mIsLoaded; + EMuteListState mLoadState; + F64 mRequestStartTime; friend class LLDispatchEmptyMuteList; }; diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index df53c66ec1..36ffcae8df 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -34,10 +34,12 @@ #include "llaccordionctrl.h" #include "llaccordionctrltab.h" #include "llagentwearables.h" +#include "llaisapi.h" #include "llappearancemgr.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llinspecttexture.h" +#include "llinventorymodelbackgroundfetch.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llmenubutton.h" @@ -205,12 +207,22 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id) list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); - // Fetch the new outfit contents. - cat->fetch(); - - // Refresh the list of outfit items after fetch(). - // Further list updates will be triggered by the category observer. - list->updateList(cat_id); + if (AISAPI::isAvailable() && LLInventoryModelBackgroundFetch::instance().folderFetchActive()) + { + // for reliability just fetch it whole, linked items included + LLInventoryModelBackgroundFetch::instance().fetchFolderAndLinks(cat_id, [cat_id, list] + { + if (list) list->updateList(cat_id); + }); + } + else + { + // Fetch the new outfit contents. + cat->fetch(); + // Refresh the list of outfit items after fetch(). + // Further list updates will be triggered by the category observer. + list->updateList(cat_id); + } // If filter is currently applied we store the initial tab state. if (!getFilterSubString().empty()) diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index 3a6a6a5ec3..f0555408dd 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -463,6 +463,7 @@ void LLPanelEmojiComplete::updateConstraints() { mEmojiHeight = mRenderRect.getHeight(); mRenderRect.stretch((mRenderRect.getWidth() - static_cast<S32>(mVisibleEmojis) * mEmojiWidth) / -2, 0); + mRenderRect.translate(-mRenderRect.mLeft, 0); // Left align emojis to fix hitboxes } updateScrollPos(); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 0086a9a86d..25dd37590d 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -276,7 +276,7 @@ LLRender::eTexIndex LLPanelFace::getMatTextureChannel() return LLRender::NORMAL_MAP; break; case MATTYPE_SPECULAR: // "Shininess (specular)" - if (getCurrentNormalMap().notNull()) + if (getCurrentSpecularMap().notNull()) return LLRender::SPECULAR_MAP; break; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index dcba891f9f..dd59979a6c 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -678,6 +678,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mVisuallyMuteSetting(AV_RENDER_NORMALLY), mMutedAVColor(LLColor4::white /* used for "uninitialize" */), mFirstFullyVisible(true), + mWaitingForMeshes(false), mFirstDecloudTime(-1.f), mFullyLoaded(false), mPreviousFullyLoaded(false), @@ -920,12 +921,12 @@ bool LLVOAvatar::isFullyTextured() const bool LLVOAvatar::hasGray() const { - return !getIsCloud() && !isFullyTextured(); + return !getHasMissingParts() && !isFullyTextured(); } S32 LLVOAvatar::getRezzedStatus() const { - if (getIsCloud()) return 0; + if (getHasMissingParts()) return 0; bool textured = isFullyTextured(); bool all_baked_loaded = allBakedTexturesCompletelyDownloaded(); if (textured && all_baked_loaded && getAttachmentCount() == mSimAttachments.size()) return 4; @@ -972,30 +973,45 @@ bool LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars) } // static -void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts, F32& avg_cloud_time, S32& cloud_avatars) +void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts, F32& avg_cloud_time, S32& cloud_avatars, S32& pending_meshes, S32& control_avatars) { counts.clear(); counts.resize(5); avg_cloud_time = 0; cloud_avatars = 0; + pending_meshes = 0; + control_avatars = 0; S32 count_avg = 0; for (LLCharacter* character : LLCharacter::sInstances) { - if (LLVOAvatar* inst = (LLVOAvatar*)character) + LLVOAvatar* inst = (LLVOAvatar*)character; + if (inst && !inst->isUIAvatar() && !inst->isSelf()) { - S32 rez_status = inst->getRezzedStatus(); - counts[rez_status]++; - F32 time = inst->getFirstDecloudTime(); - if (time >= 0) + if (inst->isControlAvatar()) { - avg_cloud_time+=time; - count_avg++; + control_avatars++; } - if (!inst->isFullyLoaded() || time < 0) + else { - // still renders as cloud - cloud_avatars++; + S32 rez_status = inst->getRezzedStatus(); + counts[rez_status]++; + F32 time = inst->getFirstDecloudTime(); + if (time >= 0) + { + avg_cloud_time += time; + count_avg++; + } + if (!inst->isFullyLoaded() || time < 0) + { + // still renders as cloud + cloud_avatars++; + if (rez_status >= 4 + && inst->mWaitingForMeshes) + { + pending_meshes++; + } + } } } } @@ -1012,7 +1028,7 @@ std::string LLVOAvatar::rezStatusToString(S32 rez_status) switch (rez_status) { case 0: - return "cloud"; + return "missing parts"; case 1: return "gray"; case 2: @@ -3474,7 +3490,7 @@ void LLVOAvatar::idleUpdateNameTagText(bool new_name) is_muted = isInMuteList(); } bool is_friend = isBuddy(); - bool is_cloud = getIsCloud(); + bool is_cloud = getHasMissingParts(); if (is_appearance != mNameAppearance) { @@ -8201,7 +8217,7 @@ bool LLVOAvatar::isVisible() const } // Determine if we have enough avatar data to render -bool LLVOAvatar::getIsCloud() const +bool LLVOAvatar::getHasMissingParts() const { if (mIsDummy) { @@ -8408,8 +8424,12 @@ bool LLVOAvatar::updateIsFullyLoaded() || (mLoadedCallbackTextures < mCallbackTextureList.size() && mLastTexCallbackAddedTime.getElapsedTimeF32() < MAX_TEXTURE_WAIT_TIME_SEC) || !mPendingAttachment.empty() || (rez_status < 3 && !isFullyBaked()) - || hasPendingAttachedMeshes() ); + if (!loading) + { + mWaitingForMeshes = hasPendingAttachedMeshes(); + loading = mWaitingForMeshes; + } // compare amount of attachments to one reported by simulator if (!isSelf() && mLastCloudAttachmentCount < mSimAttachments.size() && mSimAttachments.size() > 0) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 9eb8d3f880..178665f4c5 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -400,7 +400,7 @@ public: bool isTooComplex() const; bool visualParamWeightsAreDefault(); - virtual bool getIsCloud() const; + virtual bool getHasMissingParts() const; bool isFullyTextured() const; bool hasGray() const; S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = textured, 3 = textured and fully downloaded. @@ -427,6 +427,7 @@ protected: private: bool mFirstFullyVisible; + bool mWaitingForMeshes; F32 mFirstDecloudTime; LLFrameTimer mFirstAppearanceMessageTimer; @@ -723,7 +724,7 @@ public: bool isFullyBaked(); static bool areAllNearbyInstancesBaked(S32& grey_avatars); - static void getNearbyRezzedStats(std::vector<S32>& counts, F32& avg_cloud_time, S32& cloud_avatars); + static void getNearbyRezzedStats(std::vector<S32>& counts, F32& avg_cloud_time, S32& cloud_avatars, S32& pending_meshes, S32& control_avatars); static std::string rezStatusToString(S32 status); //-------------------------------------------------------------------- diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index ebba9ba291..8da48910c6 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1927,7 +1927,7 @@ void LLVOAvatarSelf::dumpTotalLocalTextureByteCount() LL_INFOS() << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << LL_ENDL; } -bool LLVOAvatarSelf::getIsCloud() const +bool LLVOAvatarSelf::getHasMissingParts() const { // Let people know why they're clouded without spamming them into oblivion. bool do_warn = false; @@ -2237,14 +2237,18 @@ void LLVOAvatarSelf::appearanceChangeMetricsCoro(std::string url) std::vector<S32> rez_counts; F32 avg_time; S32 total_cloud_avatars; - LLVOAvatar::getNearbyRezzedStats(rez_counts, avg_time, total_cloud_avatars); + S32 waiting_for_meshes; + S32 control_avatars; + LLVOAvatar::getNearbyRezzedStats(rez_counts, avg_time, total_cloud_avatars, waiting_for_meshes, control_avatars); for (S32 rez_stat = 0; rez_stat < rez_counts.size(); ++rez_stat) { std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat); msg["nearby"][rez_status_name] = rez_counts[rez_stat]; } + msg["nearby"]["waiting_for_meshes"] = waiting_for_meshes; msg["nearby"]["avg_decloud_time"] = avg_time; msg["nearby"]["cloud_total"] = total_cloud_avatars; + msg["nearby"]["animeshes"] = control_avatars; // std::vector<std::string> bucket_fields("timer_name","is_self","grid_x","grid_y","is_using_server_bake"); std::vector<std::string> by_fields; diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index f7cd974ab0..45985b2a80 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -129,7 +129,7 @@ public: // Loading state //-------------------------------------------------------------------- public: - /*virtual*/ bool getIsCloud() const; + /*virtual*/ bool getHasMissingParts() const; //-------------------------------------------------------------------- // Region state diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index d5e281bba8..10c68432a1 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -43,12 +43,15 @@ namespace LLStatViewer LLTrace::SampleStatHandle<> FPS_SAMPLE("fpssample"); } -void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts, F32& avg_cloud_time, S32& cloud_avatars) +void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts, F32& avg_cloud_time, S32& cloud_avatars, S32& pending_meshes, S32& control_avatars) { counts.resize(3); counts[0] = 0; counts[1] = 0; counts[2] = 1; + cloud_avatars = 0; + pending_meshes = 0; + control_avatars = 0; } // static |
